[Change] Moved A* jump pathfinding from space.c to map.c.
This commit is contained in:
parent
700e47cd57
commit
5760978e56
@ -7,6 +7,7 @@
|
||||
#include "toolkit.h"
|
||||
#include "space.h"
|
||||
#include "land.h"
|
||||
#include "map.h"
|
||||
#include "lluadef.h"
|
||||
#include "llua.h"
|
||||
|
||||
@ -190,7 +191,7 @@ static int space_jumpDist(lua_State* L) {
|
||||
else
|
||||
goal = cur_system->name;
|
||||
|
||||
s = system_getJumpPath(&jumps, start, goal);
|
||||
s = map_getJumpPath(&jumps, start, goal);
|
||||
free(s);
|
||||
|
||||
lua_pushnumber(L, jumps);
|
||||
|
226
src/map.c
226
src/map.c
@ -1,3 +1,7 @@
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "lephisto.h"
|
||||
#include "toolkit.h"
|
||||
@ -277,7 +281,7 @@ static void map_mouse(SDL_Event* event, double mx, double my) {
|
||||
map_selected = i;
|
||||
if(map_path)
|
||||
free(map_path);
|
||||
map_path = system_getJumpPath(&map_npath,
|
||||
map_path = map_getJumpPath(&map_npath,
|
||||
cur_system->name, sys->name);
|
||||
|
||||
if(map_npath == 0)
|
||||
@ -394,3 +398,223 @@ void map_jump(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* A* Algorithm fo shortest path finding. */
|
||||
|
||||
/* The node struct. */
|
||||
typedef struct SysNode_ {
|
||||
struct SysNode_* next, *gnext;
|
||||
|
||||
struct SysNode_* parent;
|
||||
StarSystem* sys;
|
||||
double r; /* Ranking. */
|
||||
int g; /* Step. */
|
||||
} SysNode;
|
||||
|
||||
static SysNode* A_gc;
|
||||
/* Prototypes. */
|
||||
static SysNode* A_newNode(StarSystem* sys, SysNode* parent);
|
||||
static double A_h(StarSystem* n, StarSystem* g);
|
||||
static double A_g(SysNode* n);
|
||||
static SysNode* A_add(SysNode* first, SysNode* cur);
|
||||
static SysNode* A_rm(SysNode* first, StarSystem* cur);
|
||||
static SysNode* A_in(SysNode* first, StarSystem* cur);
|
||||
static SysNode* A_lowest(SysNode* first);
|
||||
static void A_freeList(SysNode* first);
|
||||
|
||||
/* Creates a new node link to star system. */
|
||||
static SysNode* A_newNode(StarSystem* sys, SysNode* parent) {
|
||||
SysNode* n;
|
||||
|
||||
n = malloc(sizeof(SysNode));
|
||||
|
||||
n->next = NULL;
|
||||
n->parent = parent;
|
||||
n->sys = sys;
|
||||
n->r = DBL_MAX;
|
||||
n->g = 0.;
|
||||
|
||||
n->gnext = A_gc;
|
||||
A_gc = n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static double A_h(StarSystem* n, StarSystem* g) {
|
||||
(void)n;
|
||||
(void)g;
|
||||
/* Euclidean distance. */
|
||||
/*return sqrt(pow2(n->pos.x - g->pos.x) + pow2(n->pos.y - g->pos.y))/100.; */
|
||||
return 0.;
|
||||
}
|
||||
|
||||
/* Get the g from a node. */
|
||||
static double A_g(SysNode* n) {
|
||||
return n->g;
|
||||
}
|
||||
|
||||
/* Add a node to the linkes list. */
|
||||
static SysNode* A_add(SysNode* first, SysNode* cur) {
|
||||
SysNode* n;
|
||||
|
||||
if(first == NULL)
|
||||
return cur;
|
||||
|
||||
n = first;
|
||||
while(n->next != NULL)
|
||||
n = n->next;
|
||||
n->next = cur;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/* Remove a node from a linked list. */
|
||||
static SysNode* A_rm(SysNode* first, StarSystem* cur) {
|
||||
SysNode* n, *p;
|
||||
|
||||
if(first->sys == cur) {
|
||||
n = first->next;
|
||||
first->next = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
p = first;
|
||||
n = p->next;
|
||||
do {
|
||||
if(n->sys == cur) {
|
||||
n->next = NULL;
|
||||
p->next = n->next;
|
||||
break;
|
||||
}
|
||||
} while((n=n->next) != NULL);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/* Check if node is in linked list. */
|
||||
static SysNode* A_in(SysNode* first, StarSystem* cur) {
|
||||
SysNode* n;
|
||||
|
||||
if(first == NULL)
|
||||
return NULL;
|
||||
|
||||
n = first;
|
||||
do {
|
||||
if(n->sys == cur)
|
||||
return n;
|
||||
} while((n=n->next) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the lowest ranking node from a linked list of nodes. */
|
||||
static SysNode* A_lowest(SysNode* first) {
|
||||
SysNode* lowest, *n;
|
||||
|
||||
if(first == NULL)
|
||||
return NULL;
|
||||
|
||||
n = first;
|
||||
lowest = n;
|
||||
do {
|
||||
if(n->r < lowest->r)
|
||||
lowest = n;
|
||||
} while((n=n->next) != NULL);
|
||||
|
||||
return lowest;
|
||||
}
|
||||
|
||||
/* Free a linked list. */
|
||||
static void A_freeList(SysNode* first) {
|
||||
SysNode* p, *n;
|
||||
|
||||
if(first == NULL)
|
||||
return;
|
||||
|
||||
p = NULL;
|
||||
n = first;
|
||||
do {
|
||||
if(p != NULL)
|
||||
free(p);
|
||||
p = n;
|
||||
} while((n=n->gnext) != NULL);
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
StarSystem** map_getJumpPath(int* njumps, char* sysstart, char* sysend) {
|
||||
int i, cost;
|
||||
|
||||
StarSystem* sys, *ssys, *esys, **res;
|
||||
|
||||
SysNode* cur, *neighbour;
|
||||
SysNode* open, *closed;
|
||||
SysNode* ocost, *ccost;
|
||||
|
||||
A_gc = NULL;
|
||||
|
||||
/* Initial and target systems. */
|
||||
ssys = system_get(sysstart); /* Start. */
|
||||
esys = system_get(sysend); /* End. */
|
||||
|
||||
/* System target must be known. */
|
||||
if(!sys_isKnown(esys)) {
|
||||
if(space_sysReachable(esys)) { /* Can we still reach it? */
|
||||
res = malloc(sizeof(StarSystem*));
|
||||
(*njumps) = 1;
|
||||
res[0] = esys;
|
||||
return res;
|
||||
}
|
||||
/* Can't reach - Don't make path. */
|
||||
(*njumps) = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Start the linked lists. */
|
||||
open = closed = NULL;
|
||||
cur = A_newNode(ssys, NULL);
|
||||
open = A_add(open, cur); /* Initial open node is the start system. */
|
||||
|
||||
while((cur = A_lowest(open))->sys != esys) {
|
||||
/* Get best from open and toss to closed. */
|
||||
open = A_rm(open, cur->sys);
|
||||
closed = A_add(closed, cur);
|
||||
cost = A_g(cur) + 1;
|
||||
|
||||
for(i = 0; i < cur->sys->njumps; i++) {
|
||||
sys = &systems_stack[cur->sys->jumps[i]];
|
||||
|
||||
if(!sys_isKnown(sys)) continue;
|
||||
|
||||
neighbour = A_newNode(sys, NULL);
|
||||
|
||||
ocost = A_in(open, sys);
|
||||
if((ocost != NULL) && (cost < ocost->g)) {
|
||||
open = A_rm(open, sys); /* New path is better. */
|
||||
}
|
||||
|
||||
ccost = A_in(closed, sys);
|
||||
if(ccost != NULL) {
|
||||
closed = A_rm(closed, sys); /* Shouldn't happen. */
|
||||
}
|
||||
|
||||
if((ocost == NULL) && (ccost == NULL)) {
|
||||
neighbour->g = cost;
|
||||
neighbour->r = A_g(neighbour) + A_h(cur->sys, sys);
|
||||
neighbour->parent = cur;
|
||||
open = A_add(open, neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Build the path backwards. */
|
||||
(*njumps) = A_g(cur);
|
||||
res = malloc(sizeof(StarSystem*) * (*njumps));
|
||||
for(i = 0; i < (*njumps); i++) {
|
||||
res[(*njumps)-i-1] = cur->sys;
|
||||
cur = cur->parent;
|
||||
}
|
||||
|
||||
/* Free the linked list. */
|
||||
A_freeList(A_gc);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "space.h"
|
||||
|
||||
/* Open the map window. */
|
||||
void map_open(void);
|
||||
@ -7,3 +8,6 @@ void map_open(void);
|
||||
void map_clear(void);
|
||||
void map_jump(void);
|
||||
|
||||
/* Manipulate universe stuff. */
|
||||
StarSystem** map_getJumpPath(int* njumps, char* sysstart, char* sysend);
|
||||
|
||||
|
224
src/space.c
224
src/space.c
@ -1,6 +1,5 @@
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "xml.h"
|
||||
#include "lephisto.h"
|
||||
@ -70,7 +69,6 @@ static int nstars = 0; /* Total stars. */
|
||||
static int mstars = 0; /* Memory stars are taking. */
|
||||
|
||||
/* Intern. */
|
||||
static StarSystem* system_get(const char* sysname);
|
||||
static Planet* planet_pull(const char* name);
|
||||
static void space_addFleet(Fleet* fleet);
|
||||
static StarSystem* system_parse(const xmlNodePtr parent);
|
||||
@ -148,225 +146,7 @@ void planets_minimap(const double res, const double w,
|
||||
}
|
||||
#undef PIXEL
|
||||
|
||||
/* A* Algorithm fo shortest path finding. */
|
||||
|
||||
/* The node struct. */
|
||||
typedef struct SysNode_ {
|
||||
struct SysNode_* next, *gnext;
|
||||
|
||||
struct SysNode_* parent;
|
||||
StarSystem* sys;
|
||||
double r; /* Ranking. */
|
||||
int g; /* Step. */
|
||||
} SysNode;
|
||||
|
||||
static SysNode* A_gc;
|
||||
/* Prototypes. */
|
||||
static SysNode* A_newNode(StarSystem* sys, SysNode* parent);
|
||||
static double A_h(StarSystem* n, StarSystem* g);
|
||||
static double A_g(SysNode* n);
|
||||
static SysNode* A_add(SysNode* first, SysNode* cur);
|
||||
static SysNode* A_rm(SysNode* first, StarSystem* cur);
|
||||
static SysNode* A_in(SysNode* first, StarSystem* cur);
|
||||
static SysNode* A_lowest(SysNode* first);
|
||||
static void A_freeList(SysNode* first);
|
||||
|
||||
/* Creates a new node link to star system. */
|
||||
static SysNode* A_newNode(StarSystem* sys, SysNode* parent) {
|
||||
SysNode* n;
|
||||
|
||||
n = malloc(sizeof(SysNode));
|
||||
|
||||
n->next = NULL;
|
||||
n->parent = parent;
|
||||
n->sys = sys;
|
||||
n->r = DBL_MAX;
|
||||
n->g = 0.;
|
||||
|
||||
n->gnext = A_gc;
|
||||
A_gc = n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static double A_h(StarSystem* n, StarSystem* g) {
|
||||
(void)n;
|
||||
(void)g;
|
||||
/* Euclidean distance. */
|
||||
/*return sqrt(pow2(n->pos.x - g->pos.x) + pow2(n->pos.y - g->pos.y))/100.; */
|
||||
return 0.;
|
||||
}
|
||||
|
||||
/* Get the g from a node. */
|
||||
static double A_g(SysNode* n) {
|
||||
return n->g;
|
||||
}
|
||||
|
||||
/* Add a node to the linkes list. */
|
||||
static SysNode* A_add(SysNode* first, SysNode* cur) {
|
||||
SysNode* n;
|
||||
|
||||
if(first == NULL)
|
||||
return cur;
|
||||
|
||||
n = first;
|
||||
while(n->next != NULL)
|
||||
n = n->next;
|
||||
n->next = cur;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/* Remove a node from a linked list. */
|
||||
static SysNode* A_rm(SysNode* first, StarSystem* cur) {
|
||||
SysNode* n, *p;
|
||||
|
||||
if(first->sys == cur) {
|
||||
n = first->next;
|
||||
first->next = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
p = first;
|
||||
n = p->next;
|
||||
do {
|
||||
if(n->sys == cur) {
|
||||
n->next = NULL;
|
||||
p->next = n->next;
|
||||
break;
|
||||
}
|
||||
} while((n=n->next) != NULL);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/* Check if node is in linked list. */
|
||||
static SysNode* A_in(SysNode* first, StarSystem* cur) {
|
||||
SysNode* n;
|
||||
|
||||
if(first == NULL)
|
||||
return NULL;
|
||||
|
||||
n = first;
|
||||
do {
|
||||
if(n->sys == cur)
|
||||
return n;
|
||||
} while((n=n->next) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the lowest ranking node from a linked list of nodes. */
|
||||
static SysNode* A_lowest(SysNode* first) {
|
||||
SysNode* lowest, *n;
|
||||
|
||||
if(first == NULL)
|
||||
return NULL;
|
||||
|
||||
n = first;
|
||||
lowest = n;
|
||||
do {
|
||||
if(n->r < lowest->r)
|
||||
lowest = n;
|
||||
} while((n=n->next) != NULL);
|
||||
|
||||
return lowest;
|
||||
}
|
||||
|
||||
/* Free a linked list. */
|
||||
static void A_freeList(SysNode* first) {
|
||||
SysNode* p, *n;
|
||||
|
||||
if(first == NULL)
|
||||
return;
|
||||
|
||||
p = NULL;
|
||||
n = first;
|
||||
do {
|
||||
if(p != NULL)
|
||||
free(p);
|
||||
p = n;
|
||||
} while((n=n->gnext) != NULL);
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
StarSystem** system_getJumpPath(int* njumps, char* sysstart, char* sysend) {
|
||||
int i, cost;
|
||||
|
||||
StarSystem* sys, *ssys, *esys, **res;
|
||||
|
||||
SysNode* cur, *neighbour;
|
||||
SysNode* open, *closed;
|
||||
SysNode* ocost, *ccost;
|
||||
|
||||
A_gc = NULL;
|
||||
|
||||
/* Initial and target systems. */
|
||||
ssys = system_get(sysstart); /* Start. */
|
||||
esys = system_get(sysend); /* End. */
|
||||
|
||||
/* System target must be known. */
|
||||
if(!sys_isKnown(esys)) {
|
||||
if(space_sysReachable(esys)) { /* Can we still reach it? */
|
||||
res = malloc(sizeof(StarSystem*));
|
||||
(*njumps) = 1;
|
||||
res[0] = esys;
|
||||
return res;
|
||||
}
|
||||
/* Can't reach - Don't make path. */
|
||||
(*njumps) = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Start the linked lists. */
|
||||
open = closed = NULL;
|
||||
cur = A_newNode(ssys, NULL);
|
||||
open = A_add(open, cur); /* Initial open node is the start system. */
|
||||
|
||||
while((cur = A_lowest(open))->sys != esys) {
|
||||
/* Get best from open and toss to closed. */
|
||||
open = A_rm(open, cur->sys);
|
||||
closed = A_add(closed, cur);
|
||||
cost = A_g(cur) + 1;
|
||||
|
||||
for(i = 0; i < cur->sys->njumps; i++) {
|
||||
sys = &systems_stack[cur->sys->jumps[i]];
|
||||
|
||||
if(!sys_isKnown(sys)) continue;
|
||||
|
||||
neighbour = A_newNode(sys, NULL);
|
||||
|
||||
ocost = A_in(open, sys);
|
||||
if((ocost != NULL) && (cost < ocost->g)) {
|
||||
open = A_rm(open, sys); /* New path is better. */
|
||||
}
|
||||
|
||||
ccost = A_in(closed, sys);
|
||||
if(ccost != NULL) {
|
||||
closed = A_rm(closed, sys); /* Shouldn't happen. */
|
||||
}
|
||||
|
||||
if((ocost == NULL) && (ccost == NULL)) {
|
||||
neighbour->g = cost;
|
||||
neighbour->r = A_g(neighbour) + A_h(cur->sys, sys);
|
||||
neighbour->parent = cur;
|
||||
open = A_add(open, neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Build the path backwards. */
|
||||
(*njumps) = A_g(cur);
|
||||
res = malloc(sizeof(StarSystem*) * (*njumps));
|
||||
for(i = 0; i < (*njumps); i++) {
|
||||
res[(*njumps)-i-1] = cur->sys;
|
||||
cur = cur->parent;
|
||||
}
|
||||
|
||||
/* Free the linked list. */
|
||||
A_freeList(A_gc);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Basically return a PlanetClass integer from a char. */
|
||||
static PlanetClass planetclass_get(const char a) {
|
||||
switch(a) {
|
||||
/* Planets use letters. */
|
||||
@ -504,7 +284,7 @@ int space_sysReachable(StarSystem* sys) {
|
||||
}
|
||||
|
||||
/* Get the system from it's name. */
|
||||
static StarSystem* system_get(const char* sysname) {
|
||||
StarSystem* system_get(const char* sysname) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < systems_nstack; i++)
|
||||
|
@ -123,7 +123,7 @@ void planets_render(void);
|
||||
void space_update(const double dt);
|
||||
|
||||
/* Misc. */
|
||||
StarSystem** system_getJumpPath(int* njumps, char* sysstart, char* sysend);
|
||||
StarSystem* system_get(const char* sysname);
|
||||
int space_canHyperspace(Pilot* p);
|
||||
int space_hyperspace(Pilot* p);
|
||||
int space_sysReachable(StarSystem* sys);
|
||||
|
Loading…
Reference in New Issue
Block a user