[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 "toolkit.h"
|
||||||
#include "space.h"
|
#include "space.h"
|
||||||
#include "land.h"
|
#include "land.h"
|
||||||
|
#include "map.h"
|
||||||
#include "lluadef.h"
|
#include "lluadef.h"
|
||||||
#include "llua.h"
|
#include "llua.h"
|
||||||
|
|
||||||
@ -190,7 +191,7 @@ static int space_jumpDist(lua_State* L) {
|
|||||||
else
|
else
|
||||||
goal = cur_system->name;
|
goal = cur_system->name;
|
||||||
|
|
||||||
s = system_getJumpPath(&jumps, start, goal);
|
s = map_getJumpPath(&jumps, start, goal);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
lua_pushnumber(L, jumps);
|
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 "log.h"
|
||||||
#include "lephisto.h"
|
#include "lephisto.h"
|
||||||
#include "toolkit.h"
|
#include "toolkit.h"
|
||||||
@ -277,7 +281,7 @@ static void map_mouse(SDL_Event* event, double mx, double my) {
|
|||||||
map_selected = i;
|
map_selected = i;
|
||||||
if(map_path)
|
if(map_path)
|
||||||
free(map_path);
|
free(map_path);
|
||||||
map_path = system_getJumpPath(&map_npath,
|
map_path = map_getJumpPath(&map_npath,
|
||||||
cur_system->name, sys->name);
|
cur_system->name, sys->name);
|
||||||
|
|
||||||
if(map_npath == 0)
|
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
|
#pragma once
|
||||||
|
#include "space.h"
|
||||||
|
|
||||||
/* Open the map window. */
|
/* Open the map window. */
|
||||||
void map_open(void);
|
void map_open(void);
|
||||||
@ -7,3 +8,6 @@ void map_open(void);
|
|||||||
void map_clear(void);
|
void map_clear(void);
|
||||||
void map_jump(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 <malloc.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
|
||||||
|
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
#include "lephisto.h"
|
#include "lephisto.h"
|
||||||
@ -70,7 +69,6 @@ static int nstars = 0; /* Total stars. */
|
|||||||
static int mstars = 0; /* Memory stars are taking. */
|
static int mstars = 0; /* Memory stars are taking. */
|
||||||
|
|
||||||
/* Intern. */
|
/* Intern. */
|
||||||
static StarSystem* system_get(const char* sysname);
|
|
||||||
static Planet* planet_pull(const char* name);
|
static Planet* planet_pull(const char* name);
|
||||||
static void space_addFleet(Fleet* fleet);
|
static void space_addFleet(Fleet* fleet);
|
||||||
static StarSystem* system_parse(const xmlNodePtr parent);
|
static StarSystem* system_parse(const xmlNodePtr parent);
|
||||||
@ -148,225 +146,7 @@ void planets_minimap(const double res, const double w,
|
|||||||
}
|
}
|
||||||
#undef PIXEL
|
#undef PIXEL
|
||||||
|
|
||||||
/* A* Algorithm fo shortest path finding. */
|
/* Basically return a PlanetClass integer from a char. */
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PlanetClass planetclass_get(const char a) {
|
static PlanetClass planetclass_get(const char a) {
|
||||||
switch(a) {
|
switch(a) {
|
||||||
/* Planets use letters. */
|
/* Planets use letters. */
|
||||||
@ -504,7 +284,7 @@ int space_sysReachable(StarSystem* sys) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the system from it's name. */
|
/* Get the system from it's name. */
|
||||||
static StarSystem* system_get(const char* sysname) {
|
StarSystem* system_get(const char* sysname) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < systems_nstack; i++)
|
for(i = 0; i < systems_nstack; i++)
|
||||||
|
@ -123,7 +123,7 @@ void planets_render(void);
|
|||||||
void space_update(const double dt);
|
void space_update(const double dt);
|
||||||
|
|
||||||
/* Misc. */
|
/* Misc. */
|
||||||
StarSystem** system_getJumpPath(int* njumps, char* sysstart, char* sysend);
|
StarSystem* system_get(const char* sysname);
|
||||||
int space_canHyperspace(Pilot* p);
|
int space_canHyperspace(Pilot* p);
|
||||||
int space_hyperspace(Pilot* p);
|
int space_hyperspace(Pilot* p);
|
||||||
int space_sysReachable(StarSystem* sys);
|
int space_sysReachable(StarSystem* sys);
|
||||||
|
Loading…
Reference in New Issue
Block a user