mirror of
https://github.com/minetest/minetest.git
synced 2024-11-04 14:53:45 +01:00
Add Dijkstra A* and A* without prefetching pathfind algorithms
This commit is contained in:
parent
97f0bb0342
commit
69367aa799
@ -1186,6 +1186,20 @@ methods:
|
|||||||
^ Return world-specific perlin noise (int(worldseed)+seeddiff)
|
^ Return world-specific perlin noise (int(worldseed)+seeddiff)
|
||||||
- clear_objects()
|
- clear_objects()
|
||||||
^ clear all objects in the environments
|
^ clear all objects in the environments
|
||||||
|
- line_of_sight(pos1,pos2,stepsize) ->true/false
|
||||||
|
^ checkif there is a direct line of sight between pos1 and pos2
|
||||||
|
^ pos1 First position
|
||||||
|
^ pos2 Second position
|
||||||
|
^ stepsize smaller gives more accurate results but requires more computing
|
||||||
|
time. Default is 1.
|
||||||
|
-find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm) -> table containing path
|
||||||
|
^ returns a table of 3d points representing a path from pos1 to pos2 or nil
|
||||||
|
^ pos1: start position
|
||||||
|
^ pos2: end position
|
||||||
|
^ searchdistance: number of blocks to search in each direction
|
||||||
|
^ max_jump: maximum height difference to consider walkable
|
||||||
|
^ max_drop: maximum height difference to consider droppable
|
||||||
|
^ algorithm: A*_noprefetch(default), A*, Dijkstra
|
||||||
- spawn_tree (pos, {treedef})
|
- spawn_tree (pos, {treedef})
|
||||||
^ spawns L-System tree at given pos with definition in treedef table
|
^ spawns L-System tree at given pos with definition in treedef table
|
||||||
treedef={
|
treedef={
|
||||||
|
@ -264,6 +264,7 @@ set(common_SRCS
|
|||||||
clientserver.cpp
|
clientserver.cpp
|
||||||
staticobject.cpp
|
staticobject.cpp
|
||||||
serverlist.cpp
|
serverlist.cpp
|
||||||
|
pathfinder.cpp
|
||||||
util/serialize.cpp
|
util/serialize.cpp
|
||||||
util/directiontables.cpp
|
util/directiontables.cpp
|
||||||
util/numeric.cpp
|
util/numeric.cpp
|
||||||
|
@ -364,6 +364,29 @@ ServerMap & ServerEnvironment::getServerMap()
|
|||||||
return *m_map;
|
return *m_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize)
|
||||||
|
{
|
||||||
|
float distance = pos1.getDistanceFrom(pos2);
|
||||||
|
|
||||||
|
//calculate normalized direction vector
|
||||||
|
v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
|
||||||
|
(pos2.Y - pos1.Y)/distance,
|
||||||
|
(pos2.Z - pos1.Z)/distance);
|
||||||
|
|
||||||
|
//find out if there's a node on path between pos1 and pos2
|
||||||
|
for (float i = 1; i < distance; i += stepsize) {
|
||||||
|
v3s16 pos = floatToInt(v3f(normalized_vector.X * i,
|
||||||
|
normalized_vector.Y * i,
|
||||||
|
normalized_vector.Z * i) +pos1,BS);
|
||||||
|
|
||||||
|
MapNode n = getMap().getNodeNoEx(pos);
|
||||||
|
|
||||||
|
if(n.param0 != CONTENT_AIR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ServerEnvironment::serializePlayers(const std::string &savedir)
|
void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||||
{
|
{
|
||||||
|
@ -298,6 +298,9 @@ public:
|
|||||||
// This makes stuff happen
|
// This makes stuff happen
|
||||||
void step(f32 dtime);
|
void step(f32 dtime);
|
||||||
|
|
||||||
|
//check if there's a line of sight between two positions
|
||||||
|
bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
1081
src/pathfinder.cpp
Normal file
1081
src/pathfinder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
345
src/pathfinder.h
Normal file
345
src/pathfinder.h
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2013 sapier, sapier at gmx dot net
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PATHFINDER_H_
|
||||||
|
#define PATHFINDER_H_
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Includes */
|
||||||
|
/******************************************************************************/
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "irr_v3d.h"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Typedefs and macros */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
//#define PATHFINDER_DEBUG
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DIR_XP,
|
||||||
|
DIR_XM,
|
||||||
|
DIR_ZP,
|
||||||
|
DIR_ZM
|
||||||
|
} path_directions;
|
||||||
|
|
||||||
|
/** List of supported algorithms */
|
||||||
|
typedef enum {
|
||||||
|
DIJKSTRA, /**< Dijkstra shortest path algorithm */
|
||||||
|
A_PLAIN, /**< A* algorithm using heuristics to find a path */
|
||||||
|
A_PLAIN_NP /**< A* algorithm without prefetching of map data */
|
||||||
|
} algorithm;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* declarations */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/** c wrapper function to use from scriptapi */
|
||||||
|
std::vector<v3s16> get_Path(ServerEnvironment* env,
|
||||||
|
v3s16 source,
|
||||||
|
v3s16 destination,
|
||||||
|
unsigned int searchdistance,
|
||||||
|
unsigned int max_jump,
|
||||||
|
unsigned int max_drop,
|
||||||
|
algorithm algo);
|
||||||
|
|
||||||
|
/** representation of cost in specific direction */
|
||||||
|
class path_cost {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** default constructor */
|
||||||
|
path_cost();
|
||||||
|
|
||||||
|
/** copy constructor */
|
||||||
|
path_cost(const path_cost& b);
|
||||||
|
|
||||||
|
/** assignment operator */
|
||||||
|
path_cost& operator= (const path_cost& b);
|
||||||
|
|
||||||
|
bool valid; /**< movement is possible */
|
||||||
|
int value; /**< cost of movement */
|
||||||
|
int direction; /**< y-direction of movement */
|
||||||
|
bool updated; /**< this cost has ben calculated */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** representation of a mapnode to be used for pathfinding */
|
||||||
|
class path_gridnode {
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** default constructor */
|
||||||
|
path_gridnode();
|
||||||
|
|
||||||
|
/** copy constructor */
|
||||||
|
path_gridnode(const path_gridnode& b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assignment operator
|
||||||
|
* @param b node to copy
|
||||||
|
*/
|
||||||
|
path_gridnode& operator= (const path_gridnode& b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read cost in a specific direction
|
||||||
|
* @param dir direction of cost to fetch
|
||||||
|
*/
|
||||||
|
path_cost get_cost(v3s16 dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set cost value for movement
|
||||||
|
* @param dir direction to set cost for
|
||||||
|
* @cost cost to set
|
||||||
|
*/
|
||||||
|
void set_cost(v3s16 dir,path_cost cost);
|
||||||
|
|
||||||
|
bool valid; /**< node is on surface */
|
||||||
|
bool target; /**< node is target position */
|
||||||
|
bool source; /**< node is stating position */
|
||||||
|
int totalcost; /**< cost to move here from starting point */
|
||||||
|
v3s16 sourcedir; /**< origin of movement for current cost */
|
||||||
|
int surfaces; /**< number of surfaces with same x,z value*/
|
||||||
|
v3s16 pos; /**< real position of node */
|
||||||
|
path_cost directions[4]; /**< cost in different directions */
|
||||||
|
|
||||||
|
/* debug values */
|
||||||
|
bool is_element; /**< node is element of path detected */
|
||||||
|
char type; /**< type of node */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** class doing pathfinding */
|
||||||
|
class pathfinder {
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* default constructor
|
||||||
|
*/
|
||||||
|
pathfinder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path evaluation function
|
||||||
|
* @param env environment to look for path
|
||||||
|
* @param source origin of path
|
||||||
|
* @param destination end position of path
|
||||||
|
* @param searchdistance maximum number of nodes to look in each direction
|
||||||
|
* @param max_jump maximum number of blocks a path may jump up
|
||||||
|
* @param max_drop maximum number of blocks a path may drop
|
||||||
|
* @param algo algorithm to use for finding a path
|
||||||
|
*/
|
||||||
|
std::vector<v3s16> get_Path(ServerEnvironment* env,
|
||||||
|
v3s16 source,
|
||||||
|
v3s16 destination,
|
||||||
|
unsigned int searchdistance,
|
||||||
|
unsigned int max_jump,
|
||||||
|
unsigned int max_drop,
|
||||||
|
algorithm algo);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** data struct for storing internal information */
|
||||||
|
struct limits {
|
||||||
|
struct limit {
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
};
|
||||||
|
|
||||||
|
limit X;
|
||||||
|
limit Y;
|
||||||
|
limit Z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* helper functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform index pos to mappos
|
||||||
|
* @param ipos a index position
|
||||||
|
* @return map position
|
||||||
|
*/
|
||||||
|
v3s16 getRealPos(v3s16 ipos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform mappos to index pos
|
||||||
|
* @param pos a real pos
|
||||||
|
* @return index position
|
||||||
|
*/
|
||||||
|
v3s16 getIndexPos(v3s16 pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get gridnode at a specific index position
|
||||||
|
* @param ipos index position
|
||||||
|
* @return gridnode for index
|
||||||
|
*/
|
||||||
|
path_gridnode& getIndexElement(v3s16 ipos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* invert a 3d position
|
||||||
|
* @param pos 3d position
|
||||||
|
* @return pos *-1
|
||||||
|
*/
|
||||||
|
v3s16 invert(v3s16 pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a index is within current search area
|
||||||
|
* @param index position to validate
|
||||||
|
* @return true/false
|
||||||
|
*/
|
||||||
|
bool valid_index(v3s16 index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translate position to float position
|
||||||
|
* @param pos integer position
|
||||||
|
* @return float position
|
||||||
|
*/
|
||||||
|
v3f tov3f(v3s16 pos);
|
||||||
|
|
||||||
|
|
||||||
|
/* algorithm functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculate 2d manahttan distance to target
|
||||||
|
* @param pos position to calc distance
|
||||||
|
* @return integer distance
|
||||||
|
*/
|
||||||
|
int get_manhattandistance(v3s16 pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get best direction based uppon heuristics
|
||||||
|
* @param directions list of unchecked directions
|
||||||
|
* @param g_pos mapnode to start from
|
||||||
|
* @return direction to check
|
||||||
|
*/
|
||||||
|
v3s16 get_dir_heuristic(std::vector<v3s16>& directions,path_gridnode& g_pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* build internal data representation of search area
|
||||||
|
* @return true/false if costmap creation was successfull
|
||||||
|
*/
|
||||||
|
bool build_costmap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculate cost of movement
|
||||||
|
* @param pos real world position to start movement
|
||||||
|
* @param dir direction to move to
|
||||||
|
* @return cost information
|
||||||
|
*/
|
||||||
|
path_cost calc_cost(v3s16 pos,v3s16 dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursive update whole search areas total cost information
|
||||||
|
* @param ipos position to check next
|
||||||
|
* @param srcdir positionc checked last time
|
||||||
|
* @param total_cost cost of moving to ipos
|
||||||
|
* @param level current recursion depth
|
||||||
|
* @return true/false path to destination has been found
|
||||||
|
*/
|
||||||
|
bool update_all_costs(v3s16 ipos,v3s16 srcdir,int total_cost,int level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursive try to find a patrh to destionation
|
||||||
|
* @param ipos position to check next
|
||||||
|
* @param srcdir positionc checked last time
|
||||||
|
* @param total_cost cost of moving to ipos
|
||||||
|
* @param level current recursion depth
|
||||||
|
* @return true/false path to destination has been found
|
||||||
|
*/
|
||||||
|
bool update_cost_heuristic(v3s16 ipos,v3s16 srcdir,int current_cost,int level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursive build a vector containing all nodes from source to destination
|
||||||
|
* @param path vector to add nodes to
|
||||||
|
* @param pos pos to check next
|
||||||
|
* @param level recursion depth
|
||||||
|
*/
|
||||||
|
void build_path(std::vector<v3s16>& path,v3s16 pos, int level);
|
||||||
|
|
||||||
|
/* variables */
|
||||||
|
int m_max_index_x; /**< max index of search area in x direction */
|
||||||
|
int m_max_index_y; /**< max index of search area in y direction */
|
||||||
|
int m_max_index_z; /**< max index of search area in z direction */
|
||||||
|
|
||||||
|
|
||||||
|
int m_searchdistance; /**< max distance to search in each direction */
|
||||||
|
int m_maxdrop; /**< maximum number of blocks a path may drop */
|
||||||
|
int m_maxjump; /**< maximum number of blocks a path may jump */
|
||||||
|
int m_min_target_distance; /**< current smalest path to target */
|
||||||
|
|
||||||
|
bool m_prefetch; /**< prefetch cost data */
|
||||||
|
|
||||||
|
v3s16 m_start; /**< source position */
|
||||||
|
v3s16 m_destination; /**< destination position */
|
||||||
|
|
||||||
|
limits m_limits; /**< position limits in real map coordinates */
|
||||||
|
|
||||||
|
/** 3d grid containing all map data already collected and analyzed */
|
||||||
|
std::vector<std::vector<std::vector<path_gridnode> > > m_data;
|
||||||
|
|
||||||
|
ServerEnvironment* m_env; /**< minetest environment pointer */
|
||||||
|
|
||||||
|
#ifdef PATHFINDER_DEBUG
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print collected cost information
|
||||||
|
*/
|
||||||
|
void print_cost();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print collected cost information in a specific direction
|
||||||
|
* @param dir direction to print
|
||||||
|
*/
|
||||||
|
void print_cost(path_directions dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print type of node as evaluated
|
||||||
|
*/
|
||||||
|
void print_type();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print pathlenght for all nodes in search area
|
||||||
|
*/
|
||||||
|
void print_pathlen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print a path
|
||||||
|
* @param path path to show
|
||||||
|
*/
|
||||||
|
void print_path(std::vector<v3s16> path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print y direction for all movements
|
||||||
|
*/
|
||||||
|
void print_ydir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print y direction for moving in a specific direction
|
||||||
|
* @param dir direction to show data
|
||||||
|
*/
|
||||||
|
void print_ydir(path_directions dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to translate a direction to speaking text
|
||||||
|
* @param dir direction to translate
|
||||||
|
* @return textual name of direction
|
||||||
|
*/
|
||||||
|
std::string dir_to_name(path_directions dir);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PATHFINDER_H_ */
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "content_sao.h"
|
#include "content_sao.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "treegen.h"
|
#include "treegen.h"
|
||||||
|
#include "pathfinder.h"
|
||||||
#include "util/pointedthing.h"
|
#include "util/pointedthing.h"
|
||||||
#include "scriptapi_types.h"
|
#include "scriptapi_types.h"
|
||||||
#include "scriptapi_noise.h"
|
#include "scriptapi_noise.h"
|
||||||
@ -647,6 +648,69 @@ int EnvRef::l_clear_objects(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EnvRef::l_line_of_sight(lua_State *L) {
|
||||||
|
float stepsize = 1.0;
|
||||||
|
|
||||||
|
//infostream<<"EnvRef::l_get_node()"<<std::endl;
|
||||||
|
EnvRef *o = checkobject(L, 1);
|
||||||
|
ServerEnvironment *env = o->m_env;
|
||||||
|
if(env == NULL) return 0;
|
||||||
|
|
||||||
|
// read position 1 from lua
|
||||||
|
v3f pos1 = checkFloatPos(L, 2);
|
||||||
|
// read position 2 from lua
|
||||||
|
v3f pos2 = checkFloatPos(L, 2);
|
||||||
|
//read step size from lua
|
||||||
|
if(lua_isnumber(L, 3))
|
||||||
|
stepsize = lua_tonumber(L, 3);
|
||||||
|
|
||||||
|
return (env->line_of_sight(pos1,pos2,stepsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
int EnvRef::l_find_path(lua_State *L)
|
||||||
|
{
|
||||||
|
EnvRef *o = checkobject(L, 1);
|
||||||
|
ServerEnvironment *env = o->m_env;
|
||||||
|
|
||||||
|
if(env == NULL) return 0;
|
||||||
|
|
||||||
|
v3s16 pos1 = read_v3s16(L, 2);
|
||||||
|
v3s16 pos2 = read_v3s16(L, 3);
|
||||||
|
unsigned int searchdistance = luaL_checkint(L, 4);
|
||||||
|
unsigned int max_jump = luaL_checkint(L, 5);
|
||||||
|
unsigned int max_drop = luaL_checkint(L, 6);
|
||||||
|
algorithm algo = A_PLAIN_NP;
|
||||||
|
if(! lua_isnil(L, 7)) {
|
||||||
|
std::string algorithm = luaL_checkstring(L,7);
|
||||||
|
|
||||||
|
if (algorithm == "A*")
|
||||||
|
algo = A_PLAIN;
|
||||||
|
|
||||||
|
if (algorithm == "Dijkstra")
|
||||||
|
algo = DIJKSTRA;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<v3s16> path =
|
||||||
|
get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo);
|
||||||
|
|
||||||
|
if (path.size() > 0)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
unsigned int index = 1;
|
||||||
|
for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L,index);
|
||||||
|
push_v3s16(L, *i);
|
||||||
|
lua_settable(L, top);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int EnvRef::l_spawn_tree(lua_State *L)
|
int EnvRef::l_spawn_tree(lua_State *L)
|
||||||
{
|
{
|
||||||
EnvRef *o = checkobject(L, 1);
|
EnvRef *o = checkobject(L, 1);
|
||||||
@ -780,6 +844,8 @@ const luaL_reg EnvRef::methods[] = {
|
|||||||
luamethod(EnvRef, get_perlin_map),
|
luamethod(EnvRef, get_perlin_map),
|
||||||
luamethod(EnvRef, clear_objects),
|
luamethod(EnvRef, clear_objects),
|
||||||
luamethod(EnvRef, spawn_tree),
|
luamethod(EnvRef, spawn_tree),
|
||||||
|
luamethod(EnvRef, line_of_sight),
|
||||||
|
luamethod(EnvRef, find_path),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +137,12 @@ private:
|
|||||||
|
|
||||||
static int l_spawn_tree(lua_State *L);
|
static int l_spawn_tree(lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
|
static int l_line_of_sight(lua_State *L);
|
||||||
|
|
||||||
|
//find a path between two positions
|
||||||
|
static int l_find_path(lua_State *L);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EnvRef(ServerEnvironment *env);
|
EnvRef(ServerEnvironment *env);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user