pathfinder.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  1. /*
  2. Minetest
  3. Copyright (C) 2013 sapier, sapier at gmx dot net
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. /******************************************************************************/
  17. /* Includes */
  18. /******************************************************************************/
  19. #include "pathfinder.h"
  20. #include "environment.h"
  21. #include "map.h"
  22. #include "log.h"
  23. #ifdef PATHFINDER_DEBUG
  24. #include <iomanip>
  25. #endif
  26. #ifdef PATHFINDER_CALC_TIME
  27. #include <sys/time.h>
  28. #endif
  29. /******************************************************************************/
  30. /* Typedefs and macros */
  31. /******************************************************************************/
  32. //#define PATHFINDER_CALC_TIME
  33. /** shortcut to print a 3d pos */
  34. #define PPOS(pos) "(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
  35. #define LVL "(" << level << ")" <<
  36. #ifdef PATHFINDER_DEBUG
  37. #define DEBUG_OUT(a) std::cout << a
  38. #define INFO_TARGET std::cout
  39. #define VERBOSE_TARGET std::cout
  40. #define ERROR_TARGET std::cout
  41. #else
  42. #define DEBUG_OUT(a) while(0)
  43. #define INFO_TARGET infostream << "pathfinder: "
  44. #define VERBOSE_TARGET verbosestream << "pathfinder: "
  45. #define ERROR_TARGET errorstream << "pathfinder: "
  46. #endif
  47. /******************************************************************************/
  48. /* implementation */
  49. /******************************************************************************/
  50. std::vector<v3s16> get_Path(ServerEnvironment* env,
  51. v3s16 source,
  52. v3s16 destination,
  53. unsigned int searchdistance,
  54. unsigned int max_jump,
  55. unsigned int max_drop,
  56. algorithm algo) {
  57. pathfinder searchclass;
  58. return searchclass.get_Path(env,
  59. source,destination,
  60. searchdistance,max_jump,max_drop,algo);
  61. }
  62. /******************************************************************************/
  63. path_cost::path_cost()
  64. : valid(false),
  65. value(0),
  66. direction(0),
  67. updated(false)
  68. {
  69. //intentionaly empty
  70. }
  71. /******************************************************************************/
  72. path_cost::path_cost(const path_cost& b) {
  73. valid = b.valid;
  74. direction = b.direction;
  75. value = b.value;
  76. updated = b.updated;
  77. }
  78. /******************************************************************************/
  79. path_cost& path_cost::operator= (const path_cost& b) {
  80. valid = b.valid;
  81. direction = b.direction;
  82. value = b.value;
  83. updated = b.updated;
  84. return *this;
  85. }
  86. /******************************************************************************/
  87. path_gridnode::path_gridnode()
  88. : valid(false),
  89. target(false),
  90. source(false),
  91. totalcost(-1),
  92. sourcedir(v3s16(0,0,0)),
  93. surfaces(0),
  94. pos(v3s16(0,0,0)),
  95. is_element(false),
  96. type('u')
  97. {
  98. //intentionaly empty
  99. }
  100. /******************************************************************************/
  101. path_gridnode::path_gridnode(const path_gridnode& b)
  102. : valid(b.valid),
  103. target(b.target),
  104. source(b.source),
  105. totalcost(b.totalcost),
  106. sourcedir(b.sourcedir),
  107. surfaces(b.surfaces),
  108. pos(b.pos),
  109. is_element(b.is_element),
  110. type(b.type)
  111. {
  112. directions[DIR_XP] = b.directions[DIR_XP];
  113. directions[DIR_XM] = b.directions[DIR_XM];
  114. directions[DIR_ZP] = b.directions[DIR_ZP];
  115. directions[DIR_ZM] = b.directions[DIR_ZM];
  116. }
  117. /******************************************************************************/
  118. path_gridnode& path_gridnode::operator= (const path_gridnode& b) {
  119. valid = b.valid;
  120. target = b.target;
  121. source = b.source;
  122. is_element = b.is_element;
  123. totalcost = b.totalcost;
  124. sourcedir = b.sourcedir;
  125. surfaces = b.surfaces;
  126. pos = b.pos;
  127. type = b.type;
  128. directions[DIR_XP] = b.directions[DIR_XP];
  129. directions[DIR_XM] = b.directions[DIR_XM];
  130. directions[DIR_ZP] = b.directions[DIR_ZP];
  131. directions[DIR_ZM] = b.directions[DIR_ZM];
  132. return *this;
  133. }
  134. /******************************************************************************/
  135. path_cost path_gridnode::get_cost(v3s16 dir) {
  136. if (dir.X > 0) {
  137. return directions[DIR_XP];
  138. }
  139. if (dir.X < 0) {
  140. return directions[DIR_XM];
  141. }
  142. if (dir.Z > 0) {
  143. return directions[DIR_ZP];
  144. }
  145. if (dir.Z < 0) {
  146. return directions[DIR_ZM];
  147. }
  148. path_cost retval;
  149. return retval;
  150. }
  151. /******************************************************************************/
  152. void path_gridnode::set_cost(v3s16 dir,path_cost cost) {
  153. if (dir.X > 0) {
  154. directions[DIR_XP] = cost;
  155. }
  156. if (dir.X < 0) {
  157. directions[DIR_XM] = cost;
  158. }
  159. if (dir.Z > 0) {
  160. directions[DIR_ZP] = cost;
  161. }
  162. if (dir.Z < 0) {
  163. directions[DIR_ZM] = cost;
  164. }
  165. }
  166. /******************************************************************************/
  167. std::vector<v3s16> pathfinder::get_Path(ServerEnvironment* env,
  168. v3s16 source,
  169. v3s16 destination,
  170. unsigned int searchdistance,
  171. unsigned int max_jump,
  172. unsigned int max_drop,
  173. algorithm algo) {
  174. #ifdef PATHFINDER_CALC_TIME
  175. timespec ts;
  176. clock_gettime(CLOCK_REALTIME, &ts);
  177. #endif
  178. std::vector<v3s16> retval;
  179. //check parameters
  180. if (env == 0) {
  181. ERROR_TARGET << "missing environment pointer" << std::endl;
  182. return retval;
  183. }
  184. m_searchdistance = searchdistance;
  185. m_env = env;
  186. m_maxjump = max_jump;
  187. m_maxdrop = max_drop;
  188. m_start = source;
  189. m_destination = destination;
  190. m_min_target_distance = -1;
  191. m_prefetch = true;
  192. if (algo == A_PLAIN_NP) {
  193. m_prefetch = false;
  194. }
  195. int min_x = MYMIN(source.X,destination.X);
  196. int max_x = MYMAX(source.X,destination.X);
  197. int min_y = MYMIN(source.Y,destination.Y);
  198. int max_y = MYMAX(source.Y,destination.Y);
  199. int min_z = MYMIN(source.Z,destination.Z);
  200. int max_z = MYMAX(source.Z,destination.Z);
  201. m_limits.X.min = min_x - searchdistance;
  202. m_limits.X.max = max_x + searchdistance;
  203. m_limits.Y.min = min_y - searchdistance;
  204. m_limits.Y.max = max_y + searchdistance;
  205. m_limits.Z.min = min_z - searchdistance;
  206. m_limits.Z.max = max_z + searchdistance;
  207. m_max_index_x = m_limits.X.max - m_limits.X.min;
  208. m_max_index_y = m_limits.Y.max - m_limits.Y.min;
  209. m_max_index_z = m_limits.Z.max - m_limits.Z.min;
  210. //build data map
  211. if (!build_costmap()) {
  212. ERROR_TARGET << "failed to build costmap" << std::endl;
  213. return retval;
  214. }
  215. #ifdef PATHFINDER_DEBUG
  216. print_type();
  217. print_cost();
  218. print_ydir();
  219. #endif
  220. //validate and mark start and end pos
  221. v3s16 StartIndex = getIndexPos(source);
  222. v3s16 EndIndex = getIndexPos(destination);
  223. path_gridnode& startpos = getIndexElement(StartIndex);
  224. path_gridnode& endpos = getIndexElement(EndIndex);
  225. if (!startpos.valid) {
  226. VERBOSE_TARGET << "invalid startpos" <<
  227. "Index: " << PPOS(StartIndex) <<
  228. "Realpos: " << PPOS(getRealPos(StartIndex)) << std::endl;
  229. return retval;
  230. }
  231. if (!endpos.valid) {
  232. VERBOSE_TARGET << "invalid stoppos" <<
  233. "Index: " << PPOS(EndIndex) <<
  234. "Realpos: " << PPOS(getRealPos(EndIndex)) << std::endl;
  235. return retval;
  236. }
  237. endpos.target = true;
  238. startpos.source = true;
  239. startpos.totalcost = 0;
  240. bool update_cost_retval = false;
  241. switch (algo) {
  242. case DIJKSTRA:
  243. update_cost_retval = update_all_costs(StartIndex,v3s16(0,0,0),0,0);
  244. break;
  245. case A_PLAIN_NP:
  246. case A_PLAIN:
  247. update_cost_retval = update_cost_heuristic(StartIndex,v3s16(0,0,0),0,0);
  248. break;
  249. default:
  250. ERROR_TARGET << "missing algorithm"<< std::endl;
  251. break;
  252. }
  253. if (update_cost_retval) {
  254. #ifdef PATHFINDER_DEBUG
  255. std::cout << "Path to target found!" << std::endl;
  256. print_pathlen();
  257. #endif
  258. //find path
  259. std::vector<v3s16> path;
  260. build_path(path,EndIndex,0);
  261. #ifdef PATHFINDER_DEBUG
  262. std::cout << "Full index path:" << std::endl;
  263. print_path(path);
  264. #endif
  265. //optimize path
  266. std::vector<v3s16> optimized_path;
  267. std::vector<v3s16>::iterator startpos = path.begin();
  268. optimized_path.push_back(source);
  269. for (std::vector<v3s16>::iterator i = path.begin();
  270. i != path.end(); i++) {
  271. if (!m_env->line_of_sight(
  272. tov3f(getIndexElement(*startpos).pos),
  273. tov3f(getIndexElement(*i).pos))) {
  274. optimized_path.push_back(getIndexElement(*(i-1)).pos);
  275. startpos = (i-1);
  276. }
  277. }
  278. optimized_path.push_back(destination);
  279. #ifdef PATHFINDER_DEBUG
  280. std::cout << "Optimized path:" << std::endl;
  281. print_path(optimized_path);
  282. #endif
  283. #ifdef PATHFINDER_CALC_TIME
  284. timespec ts2;
  285. clock_gettime(CLOCK_REALTIME, &ts2);
  286. int ms = (ts2.tv_nsec - ts.tv_nsec)/(1000*1000);
  287. int us = ((ts2.tv_nsec - ts.tv_nsec) - (ms*1000*1000))/1000;
  288. int ns = ((ts2.tv_nsec - ts.tv_nsec) - ( (ms*1000*1000) + (us*1000)));
  289. std::cout << "Calculating path took: " << (ts2.tv_sec - ts.tv_sec) <<
  290. "s " << ms << "ms " << us << "us " << ns << "ns " << std::endl;
  291. #endif
  292. return optimized_path;
  293. }
  294. else {
  295. #ifdef PATHFINDER_DEBUG
  296. print_pathlen();
  297. #endif
  298. ERROR_TARGET << "failed to update cost map"<< std::endl;
  299. }
  300. //return
  301. return retval;
  302. }
  303. /******************************************************************************/
  304. pathfinder::pathfinder() :
  305. m_max_index_x(0),
  306. m_max_index_y(0),
  307. m_max_index_z(0),
  308. m_searchdistance(0),
  309. m_maxdrop(0),
  310. m_maxjump(0),
  311. m_min_target_distance(0),
  312. m_prefetch(true),
  313. m_start(0,0,0),
  314. m_destination(0,0,0),
  315. m_limits(),
  316. m_data(),
  317. m_env(0)
  318. {
  319. //intentionaly empty
  320. }
  321. /******************************************************************************/
  322. v3s16 pathfinder::getRealPos(v3s16 ipos) {
  323. v3s16 retval = ipos;
  324. retval.X += m_limits.X.min;
  325. retval.Y += m_limits.Y.min;
  326. retval.Z += m_limits.Z.min;
  327. return retval;
  328. }
  329. /******************************************************************************/
  330. bool pathfinder::build_costmap()
  331. {
  332. INFO_TARGET << "Pathfinder build costmap: (" << m_limits.X.min << ","
  333. << m_limits.Z.min << ") ("
  334. << m_limits.X.max << ","
  335. << m_limits.Z.max << ")"
  336. << std::endl;
  337. m_data.resize(m_max_index_x);
  338. for (int x = 0; x < m_max_index_x; x++) {
  339. m_data[x].resize(m_max_index_z);
  340. for (int z = 0; z < m_max_index_z; z++) {
  341. m_data[x][z].resize(m_max_index_y);
  342. int surfaces = 0;
  343. for (int y = 0; y < m_max_index_y; y++) {
  344. v3s16 ipos(x,y,z);
  345. v3s16 realpos = getRealPos(ipos);
  346. MapNode current = m_env->getMap().getNodeNoEx(realpos);
  347. MapNode below = m_env->getMap().getNodeNoEx(realpos + v3s16(0,-1,0));
  348. if ((current.param0 == CONTENT_IGNORE) ||
  349. (below.param0 == CONTENT_IGNORE)) {
  350. DEBUG_OUT("Pathfinder: " << PPOS(realpos) <<
  351. " current or below is invalid element" << std::endl);
  352. if (current.param0 == CONTENT_IGNORE) {
  353. m_data[x][z][y].type = 'i';
  354. DEBUG_OUT(x << "," << y << "," << z << ": " << 'i' << std::endl);
  355. }
  356. continue;
  357. }
  358. //don't add anything if it isn't an air node
  359. if ((current.param0 != CONTENT_AIR) ||
  360. (below.param0 == CONTENT_AIR )) {
  361. DEBUG_OUT("Pathfinder: " << PPOS(realpos)
  362. << " not on surface" << std::endl);
  363. if (current.param0 != CONTENT_AIR) {
  364. m_data[x][z][y].type = 's';
  365. DEBUG_OUT(x << "," << y << "," << z << ": " << 's' << std::endl);
  366. }
  367. else {
  368. m_data[x][z][y].type = '-';
  369. DEBUG_OUT(x << "," << y << "," << z << ": " << '-' << std::endl);
  370. }
  371. continue;
  372. }
  373. surfaces++;
  374. m_data[x][z][y].valid = true;
  375. m_data[x][z][y].pos = realpos;
  376. m_data[x][z][y].type = 'g';
  377. DEBUG_OUT(x << "," << y << "," << z << ": " << 'a' << std::endl);
  378. if (m_prefetch) {
  379. m_data[x][z][y].directions[DIR_XP] =
  380. calc_cost(realpos,v3s16( 1,0, 0));
  381. m_data[x][z][y].directions[DIR_XM] =
  382. calc_cost(realpos,v3s16(-1,0, 0));
  383. m_data[x][z][y].directions[DIR_ZP] =
  384. calc_cost(realpos,v3s16( 0,0, 1));
  385. m_data[x][z][y].directions[DIR_ZM] =
  386. calc_cost(realpos,v3s16( 0,0,-1));
  387. }
  388. }
  389. if (surfaces >= 1 ) {
  390. for (int y = 0; y < m_max_index_y; y++) {
  391. if (m_data[x][z][y].valid) {
  392. m_data[x][z][y].surfaces = surfaces;
  393. }
  394. }
  395. }
  396. }
  397. }
  398. return true;
  399. }
  400. /******************************************************************************/
  401. path_cost pathfinder::calc_cost(v3s16 pos,v3s16 dir) {
  402. path_cost retval;
  403. retval.updated = true;
  404. v3s16 pos2 = pos + dir;
  405. //check limits
  406. if ( (pos2.X < m_limits.X.min) ||
  407. (pos2.X >= m_limits.X.max) ||
  408. (pos2.Z < m_limits.Z.min) ||
  409. (pos2.Z >= m_limits.Z.max)) {
  410. DEBUG_OUT("Pathfinder: " << PPOS(pos2) <<
  411. " no cost -> out of limits" << std::endl);
  412. return retval;
  413. }
  414. MapNode node_at_pos2 = m_env->getMap().getNodeNoEx(pos2);
  415. //did we get information about node?
  416. if (node_at_pos2.param0 == CONTENT_IGNORE ) {
  417. VERBOSE_TARGET << "Pathfinder: (1) area at pos: "
  418. << PPOS(pos2) << " not loaded";
  419. return retval;
  420. }
  421. if (node_at_pos2.param0 == CONTENT_AIR) {
  422. MapNode node_below_pos2 =
  423. m_env->getMap().getNodeNoEx(pos2 + v3s16(0,-1,0));
  424. //did we get information about node?
  425. if (node_below_pos2.param0 == CONTENT_IGNORE ) {
  426. VERBOSE_TARGET << "Pathfinder: (2) area at pos: "
  427. << PPOS((pos2 + v3s16(0,-1,0))) << " not loaded";
  428. return retval;
  429. }
  430. if (node_below_pos2.param0 != CONTENT_AIR) {
  431. retval.valid = true;
  432. retval.value = 1;
  433. retval.direction = 0;
  434. DEBUG_OUT("Pathfinder: "<< PPOS(pos)
  435. << " cost same height found" << std::endl);
  436. }
  437. else {
  438. v3s16 testpos = pos2 - v3s16(0,-1,0);
  439. MapNode node_at_pos = m_env->getMap().getNodeNoEx(testpos);
  440. while ((node_at_pos.param0 != CONTENT_IGNORE) &&
  441. (node_at_pos.param0 == CONTENT_AIR) &&
  442. (testpos.Y > m_limits.Y.min)) {
  443. testpos += v3s16(0,-1,0);
  444. node_at_pos = m_env->getMap().getNodeNoEx(testpos);
  445. }
  446. //did we find surface?
  447. if ((testpos.Y >= m_limits.Y.min) &&
  448. (node_at_pos.param0 != CONTENT_IGNORE) &&
  449. (node_at_pos.param0 != CONTENT_AIR)) {
  450. if (((pos2.Y - testpos.Y)*-1) <= m_maxdrop) {
  451. retval.valid = true;
  452. retval.value = 2;
  453. //difference of y-pos +1 (target node is ABOVE solid node)
  454. retval.direction = ((testpos.Y - pos2.Y) +1);
  455. DEBUG_OUT("Pathfinder cost below height found" << std::endl);
  456. }
  457. else {
  458. INFO_TARGET << "Pathfinder:"
  459. " distance to surface below to big: "
  460. << (testpos.Y - pos2.Y) << " max: " << m_maxdrop
  461. << std::endl;
  462. }
  463. }
  464. else {
  465. DEBUG_OUT("Pathfinder: no surface below found" << std::endl);
  466. }
  467. }
  468. }
  469. else {
  470. v3s16 testpos = pos2;
  471. MapNode node_at_pos = m_env->getMap().getNodeNoEx(testpos);
  472. while ((node_at_pos.param0 != CONTENT_IGNORE) &&
  473. (node_at_pos.param0 != CONTENT_AIR) &&
  474. (testpos.Y < m_limits.Y.max)) {
  475. testpos += v3s16(0,1,0);
  476. node_at_pos = m_env->getMap().getNodeNoEx(testpos);
  477. }
  478. //did we find surface?
  479. if ((testpos.Y <= m_limits.Y.max) &&
  480. (node_at_pos.param0 == CONTENT_AIR)) {
  481. if (testpos.Y - pos2.Y <= m_maxjump) {
  482. retval.valid = true;
  483. retval.value = 2;
  484. retval.direction = (testpos.Y - pos2.Y);
  485. DEBUG_OUT("Pathfinder cost above found" << std::endl);
  486. }
  487. else {
  488. DEBUG_OUT("Pathfinder: distance to surface above to big: "
  489. << (testpos.Y - pos2.Y) << " max: " << m_maxjump
  490. << std::endl);
  491. }
  492. }
  493. else {
  494. DEBUG_OUT("Pathfinder: no surface above found" << std::endl);
  495. }
  496. }
  497. return retval;
  498. }
  499. /******************************************************************************/
  500. v3s16 pathfinder::getIndexPos(v3s16 pos) {
  501. v3s16 retval = pos;
  502. retval.X -= m_limits.X.min;
  503. retval.Y -= m_limits.Y.min;
  504. retval.Z -= m_limits.Z.min;
  505. return retval;
  506. }
  507. /******************************************************************************/
  508. path_gridnode& pathfinder::getIndexElement(v3s16 ipos) {
  509. return m_data[ipos.X][ipos.Z][ipos.Y];
  510. }
  511. /******************************************************************************/
  512. bool pathfinder::valid_index(v3s16 index) {
  513. if ( (index.X < m_max_index_x) &&
  514. (index.Y < m_max_index_y) &&
  515. (index.Z < m_max_index_z) &&
  516. (index.X >= 0) &&
  517. (index.Y >= 0) &&
  518. (index.Z >= 0))
  519. return true;
  520. return false;
  521. }
  522. /******************************************************************************/
  523. v3s16 pathfinder::invert(v3s16 pos) {
  524. v3s16 retval = pos;
  525. retval.X *=-1;
  526. retval.Y *=-1;
  527. retval.Z *=-1;
  528. return retval;
  529. }
  530. /******************************************************************************/
  531. bool pathfinder::update_all_costs( v3s16 ipos,
  532. v3s16 srcdir,
  533. int current_cost,
  534. int level) {
  535. path_gridnode& g_pos = getIndexElement(ipos);
  536. g_pos.totalcost = current_cost;
  537. g_pos.sourcedir = srcdir;
  538. level ++;
  539. //check if target has been found
  540. if (g_pos.target) {
  541. m_min_target_distance = current_cost;
  542. DEBUG_OUT(LVL " Pathfinder: target found!" << std::endl);
  543. return true;
  544. }
  545. bool retval = false;
  546. std::vector<v3s16> directions;
  547. directions.push_back(v3s16( 1,0, 0));
  548. directions.push_back(v3s16(-1,0, 0));
  549. directions.push_back(v3s16( 0,0, 1));
  550. directions.push_back(v3s16( 0,0,-1));
  551. for (unsigned int i=0; i < directions.size(); i++) {
  552. if (directions[i] != srcdir) {
  553. path_cost cost = g_pos.get_cost(directions[i]);
  554. if (cost.valid) {
  555. directions[i].Y = cost.direction;
  556. v3s16 ipos2 = ipos + directions[i];
  557. if (!valid_index(ipos2)) {
  558. DEBUG_OUT(LVL " Pathfinder: " << PPOS(ipos2) <<
  559. " out of range (" << m_limits.X.max << "," <<
  560. m_limits.Y.max << "," << m_limits.Z.max
  561. <<")" << std::endl);
  562. continue;
  563. }
  564. path_gridnode& g_pos2 = getIndexElement(ipos2);
  565. if (!g_pos2.valid) {
  566. VERBOSE_TARGET << LVL "Pathfinder: no data for new position: "
  567. << PPOS(ipos2) << std::endl;
  568. continue;
  569. }
  570. assert(cost.value > 0);
  571. int new_cost = current_cost + cost.value;
  572. // check if there already is a smaller path
  573. if ((m_min_target_distance > 0) &&
  574. (m_min_target_distance < new_cost)) {
  575. return false;
  576. }
  577. if ((g_pos2.totalcost < 0) ||
  578. (g_pos2.totalcost > new_cost)) {
  579. DEBUG_OUT(LVL "Pathfinder: updating path at: "<<
  580. PPOS(ipos2) << " from: " << g_pos2.totalcost << " to "<<
  581. new_cost << std::endl);
  582. if (update_all_costs(ipos2,invert(directions[i]),
  583. new_cost,level)) {
  584. retval = true;
  585. }
  586. }
  587. else {
  588. DEBUG_OUT(LVL "Pathfinder:"
  589. " already found shorter path to: "
  590. << PPOS(ipos2) << std::endl);
  591. }
  592. }
  593. else {
  594. DEBUG_OUT(LVL "Pathfinder:"
  595. " not moving to invalid direction: "
  596. << PPOS(directions[i]) << std::endl);
  597. }
  598. }
  599. }
  600. return retval;
  601. }
  602. /******************************************************************************/
  603. int pathfinder::get_manhattandistance(v3s16 pos) {
  604. int min_x = MYMIN(pos.X,m_destination.X);
  605. int max_x = MYMAX(pos.X,m_destination.X);
  606. int min_z = MYMIN(pos.Z,m_destination.Z);
  607. int max_z = MYMAX(pos.Z,m_destination.Z);
  608. return (max_x - min_x) + (max_z - min_z);
  609. }
  610. /******************************************************************************/
  611. v3s16 pathfinder::get_dir_heuristic(std::vector<v3s16>& directions,path_gridnode& g_pos) {
  612. int minscore = -1;
  613. v3s16 retdir = v3s16(0,0,0);
  614. v3s16 srcpos = g_pos.pos;
  615. DEBUG_OUT("Pathfinder: remaining dirs at beginning:"
  616. << directions.size() << std::endl);
  617. for (std::vector<v3s16>::iterator iter = directions.begin();
  618. iter != directions.end();
  619. iter ++) {
  620. v3s16 pos1 = v3s16(srcpos.X + iter->X,0,srcpos.Z+iter->Z);
  621. int cur_manhattan = get_manhattandistance(pos1);
  622. path_cost cost = g_pos.get_cost(*iter);
  623. if (!cost.updated) {
  624. cost = calc_cost(g_pos.pos,*iter);
  625. g_pos.set_cost(*iter,cost);
  626. }
  627. if (cost.valid) {
  628. int score = cost.value + cur_manhattan;
  629. if ((minscore < 0)|| (score < minscore)) {
  630. minscore = score;
  631. retdir = *iter;
  632. }
  633. }
  634. }
  635. if (retdir != v3s16(0,0,0)) {
  636. for (std::vector<v3s16>::iterator iter = directions.begin();
  637. iter != directions.end();
  638. iter ++) {
  639. if(*iter == retdir) {
  640. DEBUG_OUT("Pathfinder: removing return direction" << std::endl);
  641. directions.erase(iter);
  642. break;
  643. }
  644. }
  645. }
  646. else {
  647. DEBUG_OUT("Pathfinder: didn't find any valid direction clearing"
  648. << std::endl);
  649. directions.clear();
  650. }
  651. DEBUG_OUT("Pathfinder: remaining dirs at end:" << directions.size()
  652. << std::endl);
  653. return retdir;
  654. }
  655. /******************************************************************************/
  656. bool pathfinder::update_cost_heuristic( v3s16 ipos,
  657. v3s16 srcdir,
  658. int current_cost,
  659. int level) {
  660. path_gridnode& g_pos = getIndexElement(ipos);
  661. g_pos.totalcost = current_cost;
  662. g_pos.sourcedir = srcdir;
  663. level ++;
  664. //check if target has been found
  665. if (g_pos.target) {
  666. m_min_target_distance = current_cost;
  667. DEBUG_OUT(LVL " Pathfinder: target found!" << std::endl);
  668. return true;
  669. }
  670. bool retval = false;
  671. std::vector<v3s16> directions;
  672. directions.push_back(v3s16( 1,0, 0));
  673. directions.push_back(v3s16(-1,0, 0));
  674. directions.push_back(v3s16( 0,0, 1));
  675. directions.push_back(v3s16( 0,0,-1));
  676. v3s16 direction = get_dir_heuristic(directions,g_pos);
  677. while (direction != v3s16(0,0,0) && (!retval)) {
  678. if (direction != srcdir) {
  679. path_cost cost = g_pos.get_cost(direction);
  680. if (cost.valid) {
  681. direction.Y = cost.direction;
  682. v3s16 ipos2 = ipos + direction;
  683. if (!valid_index(ipos2)) {
  684. DEBUG_OUT(LVL " Pathfinder: " << PPOS(ipos2) <<
  685. " out of range (" << m_limits.X.max << "," <<
  686. m_limits.Y.max << "," << m_limits.Z.max
  687. <<")" << std::endl);
  688. direction = get_dir_heuristic(directions,g_pos);
  689. continue;
  690. }
  691. path_gridnode& g_pos2 = getIndexElement(ipos2);
  692. if (!g_pos2.valid) {
  693. VERBOSE_TARGET << LVL "Pathfinder: no data for new position: "
  694. << PPOS(ipos2) << std::endl;
  695. direction = get_dir_heuristic(directions,g_pos);
  696. continue;
  697. }
  698. assert(cost.value > 0);
  699. int new_cost = current_cost + cost.value;
  700. // check if there already is a smaller path
  701. if ((m_min_target_distance > 0) &&
  702. (m_min_target_distance < new_cost)) {
  703. DEBUG_OUT(LVL "Pathfinder:"
  704. " already longer than best already found path "
  705. << PPOS(ipos2) << std::endl);
  706. return false;
  707. }
  708. if ((g_pos2.totalcost < 0) ||
  709. (g_pos2.totalcost > new_cost)) {
  710. DEBUG_OUT(LVL "Pathfinder: updating path at: "<<
  711. PPOS(ipos2) << " from: " << g_pos2.totalcost << " to "<<
  712. new_cost << " srcdir=" <<
  713. PPOS(invert(direction))<< std::endl);
  714. if (update_cost_heuristic(ipos2,invert(direction),
  715. new_cost,level)) {
  716. retval = true;
  717. }
  718. }
  719. else {
  720. DEBUG_OUT(LVL "Pathfinder:"
  721. " already found shorter path to: "
  722. << PPOS(ipos2) << std::endl);
  723. }
  724. }
  725. else {
  726. DEBUG_OUT(LVL "Pathfinder:"
  727. " not moving to invalid direction: "
  728. << PPOS(direction) << std::endl);
  729. }
  730. }
  731. else {
  732. DEBUG_OUT(LVL "Pathfinder:"
  733. " skipping srcdir: "
  734. << PPOS(direction) << std::endl);
  735. }
  736. direction = get_dir_heuristic(directions,g_pos);
  737. }
  738. return retval;
  739. }
  740. /******************************************************************************/
  741. void pathfinder::build_path(std::vector<v3s16>& path,v3s16 pos, int level) {
  742. level ++;
  743. if (level > 700) {
  744. ERROR_TARGET
  745. << LVL "Pathfinder: path is too long aborting" << std::endl;
  746. return;
  747. }
  748. path_gridnode& g_pos = getIndexElement(pos);
  749. if (!g_pos.valid) {
  750. ERROR_TARGET
  751. << LVL "Pathfinder: invalid next pos detected aborting" << std::endl;
  752. return;
  753. }
  754. g_pos.is_element = true;
  755. //check if source reached
  756. if (g_pos.source) {
  757. path.push_back(pos);
  758. return;
  759. }
  760. build_path(path,pos + g_pos.sourcedir,level);
  761. path.push_back(pos);
  762. }
  763. /******************************************************************************/
  764. v3f pathfinder::tov3f(v3s16 pos) {
  765. return v3f(BS*pos.X,BS*pos.Y,BS*pos.Z);
  766. }
  767. #ifdef PATHFINDER_DEBUG
  768. /******************************************************************************/
  769. void pathfinder::print_cost() {
  770. print_cost(DIR_XP);
  771. print_cost(DIR_XM);
  772. print_cost(DIR_ZP);
  773. print_cost(DIR_ZM);
  774. }
  775. /******************************************************************************/
  776. void pathfinder::print_ydir() {
  777. print_ydir(DIR_XP);
  778. print_ydir(DIR_XM);
  779. print_ydir(DIR_ZP);
  780. print_ydir(DIR_ZM);
  781. }
  782. /******************************************************************************/
  783. void pathfinder::print_cost(path_directions dir) {
  784. std::cout << "Cost in direction: " << dir_to_name(dir) << std::endl;
  785. std::cout << std::setfill('-') << std::setw(80) << "-" << std::endl;
  786. std::cout << std::setfill(' ');
  787. for (int y = 0; y < m_max_index_y; y++) {
  788. std::cout << "Level: " << y << std::endl;
  789. std::cout << std::setw(4) << " " << " ";
  790. for (int x = 0; x < m_max_index_x; x++) {
  791. std::cout << std::setw(4) << x;
  792. }
  793. std::cout << std::endl;
  794. for (int z = 0; z < m_max_index_z; z++) {
  795. std::cout << std::setw(4) << z <<": ";
  796. for (int x = 0; x < m_max_index_x; x++) {
  797. if (m_data[x][z][y].directions[dir].valid)
  798. std::cout << std::setw(4)
  799. << m_data[x][z][y].directions[dir].value;
  800. else
  801. std::cout << std::setw(4) << "-";
  802. }
  803. std::cout << std::endl;
  804. }
  805. std::cout << std::endl;
  806. }
  807. }
  808. /******************************************************************************/
  809. void pathfinder::print_ydir(path_directions dir) {
  810. std::cout << "Height difference in direction: " << dir_to_name(dir) << std::endl;
  811. std::cout << std::setfill('-') << std::setw(80) << "-" << std::endl;
  812. std::cout << std::setfill(' ');
  813. for (int y = 0; y < m_max_index_y; y++) {
  814. std::cout << "Level: " << y << std::endl;
  815. std::cout << std::setw(4) << " " << " ";
  816. for (int x = 0; x < m_max_index_x; x++) {
  817. std::cout << std::setw(4) << x;
  818. }
  819. std::cout << std::endl;
  820. for (int z = 0; z < m_max_index_z; z++) {
  821. std::cout << std::setw(4) << z <<": ";
  822. for (int x = 0; x < m_max_index_x; x++) {
  823. if (m_data[x][z][y].directions[dir].valid)
  824. std::cout << std::setw(4)
  825. << m_data[x][z][y].directions[dir].direction;
  826. else
  827. std::cout << std::setw(4) << "-";
  828. }
  829. std::cout << std::endl;
  830. }
  831. std::cout << std::endl;
  832. }
  833. }
  834. /******************************************************************************/
  835. void pathfinder::print_type() {
  836. std::cout << "Type of node:" << std::endl;
  837. std::cout << std::setfill('-') << std::setw(80) << "-" << std::endl;
  838. std::cout << std::setfill(' ');
  839. for (int y = 0; y < m_max_index_y; y++) {
  840. std::cout << "Level: " << y << std::endl;
  841. std::cout << std::setw(3) << " " << " ";
  842. for (int x = 0; x < m_max_index_x; x++) {
  843. std::cout << std::setw(3) << x;
  844. }
  845. std::cout << std::endl;
  846. for (int z = 0; z < m_max_index_z; z++) {
  847. std::cout << std::setw(3) << z <<": ";
  848. for (int x = 0; x < m_max_index_x; x++) {
  849. char toshow = m_data[x][z][y].type;
  850. std::cout << std::setw(3) << toshow;
  851. }
  852. std::cout << std::endl;
  853. }
  854. std::cout << std::endl;
  855. }
  856. std::cout << std::endl;
  857. }
  858. /******************************************************************************/
  859. void pathfinder::print_pathlen() {
  860. std::cout << "Pathlen:" << std::endl;
  861. std::cout << std::setfill('-') << std::setw(80) << "-" << std::endl;
  862. std::cout << std::setfill(' ');
  863. for (int y = 0; y < m_max_index_y; y++) {
  864. std::cout << "Level: " << y << std::endl;
  865. std::cout << std::setw(3) << " " << " ";
  866. for (int x = 0; x < m_max_index_x; x++) {
  867. std::cout << std::setw(3) << x;
  868. }
  869. std::cout << std::endl;
  870. for (int z = 0; z < m_max_index_z; z++) {
  871. std::cout << std::setw(3) << z <<": ";
  872. for (int x = 0; x < m_max_index_x; x++) {
  873. std::cout << std::setw(3) << m_data[x][z][y].totalcost;
  874. }
  875. std::cout << std::endl;
  876. }
  877. std::cout << std::endl;
  878. }
  879. std::cout << std::endl;
  880. }
  881. /******************************************************************************/
  882. std::string pathfinder::dir_to_name(path_directions dir) {
  883. switch (dir) {
  884. case DIR_XP:
  885. return "XP";
  886. break;
  887. case DIR_XM:
  888. return "XM";
  889. break;
  890. case DIR_ZP:
  891. return "ZP";
  892. break;
  893. case DIR_ZM:
  894. return "ZM";
  895. break;
  896. default:
  897. return "UKN";
  898. }
  899. }
  900. /******************************************************************************/
  901. void pathfinder::print_path(std::vector<v3s16> path) {
  902. unsigned int current = 0;
  903. for (std::vector<v3s16>::iterator i = path.begin();
  904. i != path.end(); i++) {
  905. std::cout << std::setw(3) << current << ":" << PPOS((*i)) << std::endl;
  906. current++;
  907. }
  908. }
  909. #endif