<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Path-finding issue</title>
		<link>http://www.allegro.cc/forums/view/562059</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Sat, 28 Jan 2006 08:26:57 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hi!</p><p>I am just working on a test-program for my path-finding algorithm and I found out that it doesn&#39;t always work correct. Here are the files:</p><p>path.cpp<br />[code path.cpp]<br />#include &quot;path.h&quot;</p><p>void load(const string&amp; filename)<br />{<br />  ifstream file(filename.c_str());</p><p>  map.resize(MAPSIZE);<br />  for(int i = 0;i &lt; MAPSIZE;i++)<br />    map&lt;i&gt;.resize(MAPSIZE);</p><p>  if(file.is_open())<br />  {<br />    string line;</p><p>    // read the map and store it<br />    for(int i = 0;i &lt; MAPSIZE;i++)<br />    {<br />      if (getline(file,line,&#39;\n&#39;))<br />      {<br />        for(int j = 0;j &lt; MAPSIZE;j++)<br />        {<br />          map[j]&lt;i&gt; = line[j];<br />          if (line[j] == &#39;A&#39;)<br />          {<br />            ac = j;<br />            ar = i;<br />          }<br />          if (line[j] == &#39;B&#39;)<br />          {<br />            bc = j;<br />            br = i;<br />          }<br />        }<br />      }<br />      else<br />      {<br />        cout &lt;&lt; &quot;Error while parsing the map!&quot; &lt;&lt; endl;<br />        exit(-1);<br />      }<br />    }</p><p>    // read the start<br />    getline(file,line,&#39;\n&#39;);<br />    if (sscanf(line.c_str(), &quot;%d %d&quot;, &amp;ac, &amp;ar) &lt; 2)<br />    {<br />      cout &lt;&lt; &quot;Error while parsing the map!&quot; &lt;&lt; endl;<br />      exit(-1);<br />    }</p><p>    // read the target<br />    getline(file,line,&#39;\n&#39;);<br />    if (sscanf(line.c_str(), &quot;%d %d %d %d&quot;, &amp;bc, &amp;br, &amp;bw, &amp;bh) &lt; 4)<br />    {<br />      cout &lt;&lt; &quot;Error while parsing the map!&quot; &lt;&lt; endl;<br />      exit(-1);<br />    }<br />  }<br />  else<br />  {<br />    cout &lt;&lt; &quot;Couldn&#39;t open mapfile!&quot; &lt;&lt; endl;<br />    exit(-1);<br />  }</p><p>  return;<br />}</p><p>int get_h(int ac, int ar, int bc, int br)<br />{<br />  int delta_x = abs(ac - bc);<br />  int delta_y = abs(ar - br);<br />  //return (static_cast&lt;int&gt;(fabs(sqrt(pow(delta_x, 2) + pow(delta_y, 2)) * 10.0f)));<br />  return ((abs(ac - bc) + abs(ar - br)) * 10);<br />}</p><p>bool node_valid(int c, int r)<br />{<br />  if (c &gt; MAPSIZE - 1 || c &lt; 0 || r &gt; MAPSIZE - 1 || c &lt; 0)<br />    return false;<br />  return true;<br />}</p><p>bool node_in_list(int c, int r, list&lt;CNode*&gt;&amp; list_)<br />{<br />  list&lt;CNode*&gt;::iterator it = list_.begin();<br />  while(it != list_.end())<br />  {<br />    if ((*it)-&gt;get_c() == c &amp;&amp; (*it)-&gt;get_r() == r)<br />      return true;<br />    *it++;<br />  }<br />  return false;<br />}</p><p>void delete_list(list&lt;CNode*&gt;&amp; list_)<br />{<br />  list&lt;CNode*&gt;::iterator it = list_.begin();<br />  while(it != list_.end())<br />    delete *it++;<br />}</p><p>list&lt;CNode*&gt;::iterator get_best_f(list&lt;CNode*&gt;&amp; list_)<br />{<br />  list&lt;CNode*&gt;::iterator best = list_.begin();<br />  list&lt;CNode*&gt;::iterator it = list_.begin();<br />  while(it != list_.end())<br />  {<br />    if ((*it)-&gt;get_f() &lt; (*best)-&gt;get_f())<br />      best = it;<br />    it++;<br />  }<br />  return best;<br />}</p><p>bool create_path(void)<br />{</p><p>  // see, if we can return immediately<br />  if (ac == bc &amp;&amp; ar == br)<br />    return true;</p><p>  // add the current node to the closedlist<br />  closedlist.push_front(new CNode(ac, ar, 0, get_h(ac, ar, bc, br)));</p><p>  // create a target-node ( not in one of the lists ), so we can use target_reached() more easily<br />  //const CNode* tar = new CNode(target-&gt;get_c(), target-&gt;get_r(), 0, 0);</p><p>  // set the current node, which will be altered during the walk through the map<br />  const CNode* cur = closedlist.front();</p><p>  while(cur-&gt;get_c() != bc || cur-&gt;get_r() != br)<br />  {<br />    int c, r;<br />    int i;</p><p>    // add the surrounding nodes to the openlist (in a random order)<br />    vector&lt;int&gt; tmp(8);<br />    for(i = 0;i &lt; 8;i++)<br />      tmp&lt;i&gt; = i;<br />    random_shuffle(tmp.begin(), tmp.end());<br />    for(i = 0;i &lt; 8;i++)<br />    {<br />      int g_modifier = 10;<br />      c = cur-&gt;get_c();<br />      r = cur-&gt;get_r();</p><p>      if (tmp&lt;i&gt; == 0)<br />        c++;<br />      else if (tmp&lt;i&gt; == 1)<br />        c--;<br />      else if (tmp&lt;i&gt; == 2)<br />        r++;<br />      else if (tmp&lt;i&gt; == 3)<br />        r--;<br />      else if (tmp&lt;i&gt; == 4)<br />      {<br />        c++;<br />        r++;<br />        g_modifier += 4;<br />      }<br />      else if (tmp&lt;i&gt; == 5)<br />      {<br />        c--;<br />        r++;<br />        g_modifier += 4;<br />      }<br />      else if (tmp&lt;i&gt; == 6)<br />      {<br />        r--;<br />        c++;<br />        g_modifier += 4;<br />      }<br />      else if (tmp&lt;i&gt; == 7)<br />      {<br />        r--;<br />        c--;<br />        g_modifier += 4;<br />      }</p><p>      if (node_valid(c, r) &amp;&amp; map[c][r] != &#39;1&#39; &amp;&amp; !node_in_list(c, r, openlist) &amp;&amp; !node_in_list(c, r, closedlist))<br />      {<br />        openlist.push_front(new CNode(c, r, cur-&gt;get_g() + g_modifier, get_h(c, r, bc, br), cur));<br />      }<br />    }</p><p>    // check, if the openlist is empty or the closedlist too full<br />    if (!openlist.size() || int(closedlist.size()) &gt; MAX_NODE_CHECKS)<br />      return false;</p><p>    // put the node with the best f-value in the closedlist<br />    list&lt;CNode*&gt;::iterator best_f = get_best_f(openlist);<br />    closedlist.push_front(*best_f);<br />    openlist.erase(best_f);</p><p>    // change the cur-variable<br />    cur = *best_f;<br />  }</p><p>  // coming here, it means that there is a valid path<br />  // now track back the way to the start by accessing the parent and save it in the path-variable<br />  while(cur != closedlist.back())<br />  { // while start not reached<br />    path.push_back(new CNode(*cur));<br />    cur = cur-&gt;get_parent();<br />  }</p><p>  return true;<br />}</p><p>void save_screenshot(const char *path)<br />{<br />  BITMAP *bmp = create_bitmap(SCREEN_W,SCREEN_H);<br />  if(!bmp) return;<br />  unsigned char *buff = new unsigned char[4*SCREEN_W*SCREEN_H];<br />  if(!buff)<br />  {<br />    destroy_bitmap(bmp);<br />    return;<br />  }</p><p>  glReadPixels(0,0,SCREEN_W,SCREEN_H,GL_RGBA,GL_UNSIGNED_BYTE,buff);</p><p>  int y;<br />  for(y=0;y&lt;SCREEN_H;y++)<br />    memcpy(bmp-&gt;line[y],buff+4*SCREEN_W*(SCREEN_H-1-y),4*SCREEN_W);</p><p>  save_bitmap(path,bmp,NULL);</p><p>  destroy_bitmap(bmp);<br />  delete buff;<br />}</p><p>void draw(void)<br />{<br />  GfxRend::FillScreen(Rgba::WHITE);</p><p>  // draw the grid<br />  for(int i = 0;i &lt; MAPSIZE;i++)<br />  {<br />    GfxRend::Line(i * TILESIZE, 0.0f, i * TILESIZE, MAPSIZE * TILESIZE, Rgba::BLACK);<br />    for(int j = 0;j &lt; MAPSIZE;j++)<br />      GfxRend::Line(0.0f, j * TILESIZE, MAPSIZE * TILESIZE, j * TILESIZE, Rgba::BLACK);<br />  }</p><p>  // draw the obstacles<br />  for(int i = 0;i &lt; MAPSIZE;i++)<br />    for(int j = 0;j &lt; MAPSIZE;j++)<br />      if (map&lt;i&gt;[j] == &#39;1&#39;)<br />        GfxRend::Rect(i * TILESIZE, j * TILESIZE, TILESIZE, TILESIZE, Rgba::BLACK);</p><p>  // draw the openlist<br />  for(list&lt;CNode*&gt;::const_iterator it = openlist.begin();it != openlist.end();it++)<br />  {<br />    int x = (*it)-&gt;get_c() * TILESIZE;<br />    int y = (*it)-&gt;get_r() * TILESIZE;<br />    GfxRend::Rect(x, y, TILESIZE, TILESIZE, Rgba::GREEN);<br />    CText::o().write((*it)-&gt;get_g(), x, y, &quot;G&quot;);<br />    CText::o().write((*it)-&gt;get_h(), x, y + 8, &quot;H&quot;);<br />    CText::o().write((*it)-&gt;get_f(), x, y + 16, &quot;F&quot;);<br />  }</p><p>    // draw the closedlist<br />  for(list&lt;CNode*&gt;::const_iterator it = closedlist.begin();it != closedlist.end();it++)<br />  {<br />    int x = (*it)-&gt;get_c() * TILESIZE;<br />    int y = (*it)-&gt;get_r() * TILESIZE;<br />    GfxRend::Rect(x, y, TILESIZE, TILESIZE, Rgba::RED);<br />    CText::o().write((*it)-&gt;get_g(), x, y, &quot;G&quot;);<br />    CText::o().write((*it)-&gt;get_h(), x, y + 8, &quot;H&quot;);<br />    CText::o().write((*it)-&gt;get_f(), x, y + 16, &quot;F&quot;);<br />  }</p><p>  // draw the path<br />  for(list&lt;CNode*&gt;::const_iterator it = path.begin();it != path.end();it++)<br />  {<br />    int x = (*it)-&gt;get_c() * TILESIZE;<br />    int y = (*it)-&gt;get_r() * TILESIZE;<br />    GfxRend::Rect(x, y, TILESIZE, TILESIZE, Rgba::BLUE);<br />    CText::o().write((*it)-&gt;get_g(), x, y, &quot;G&quot;);<br />    CText::o().write((*it)-&gt;get_h(), x, y + 8, &quot;H&quot;);<br />    CText::o().write((*it)-&gt;get_f(), x, y + 16, &quot;F&quot;);<br />  }</p><p>  GfxRend::RefreshScreen();</p><p>  save_screenshot(&quot;screenshot.png&quot;);<br />}</p><p>void unload(void)<br />{<br />  for(int i = 0;i &lt; MAPSIZE;i++)<br />    map&lt;i&gt;.resize(0);<br />  map.resize(0);<br />}</p><p>int main(void)<br />{<br />  Setup::SetupProgram();<br />  Settings::StoreMemoryBitmaps(true);<br />  Setup::SetupScreen(SCREENW, SCREENH, WINDOWED);<br />  set_color_depth(32);<br />  Settings::SetAntialiasing(true);<br />  CText::o().init();</p><p>  // load the map<br />  load(&quot;map/map.map&quot;);</p><p>  // create the path<br />  if (!create_path())<br />  {<br />    cout &lt;&lt; &quot;Can&#39;t create path!&quot; &lt;&lt; endl;<br />    return 0;<br />  }</p><p>  // draw the path<br />  draw();</p><p>  // loop<br />  while(!key[KEY_ESC])<br />    ;</p><p>  // destroy the path and the lists<br />  delete_list(path);<br />  delete_list(openlist);<br />  delete_list(closedlist);</p><p>  // unload the map<br />  unload();<br />}<br />END_OF_MAIN()<br />&lt;/code&gt;</p><p>path.h<br />[code path.h]<br />#ifndef __PATH_H<br />#define __PATH_H</p><p>#include &lt;OpenLayer.hpp&gt;<br />#include &lt;loadpng.h&gt;<br />#include &lt;vector&gt;<br />#include &lt;string&gt;<br />#include &lt;fstream&gt;<br />#include &lt;iostream&gt;<br />#include &lt;list&gt;</p><p>#include &quot;node.h&quot;<br />#include &quot;text.h&quot;</p><p>using namespace ol;<br />using std::vector;<br />using std::string;<br />using std::ifstream;<br />using std::cout;<br />using std::endl;<br />using std::list;<br />using std::pair;</p><p>vector&lt; vector&lt;char&gt; &gt; map;<br />list&lt;CNode*&gt; openlist;<br />list&lt;CNode*&gt; closedlist;<br />list&lt;CNode*&gt; path;<br />int ac;<br />int ar;<br />int bc;<br />int br;<br />int bw;<br />int bh;</p><p>const static int SCREENW = 800;<br />const static int SCREENH = 600;<br />const static int MAPSIZE = 20;<br />const static int TILESIZE = 30;<br />const static int MAX_NODE_CHECKS = 10000;</p><p>#endif<br />&lt;/code&gt;</p><p>node.cpp<br />[code node.cpp]<br />#include &quot;node.h&quot;</p><p>CNode::CNode(int c, int r, int g, int h, const CNode* parent)<br />{<br />  c_ = c;<br />  r_ = r;<br />  g_ = g;<br />  h_ = h;<br />  f_ = g + h;<br />  parent_ = parent;<br />}</p><p>CNode::~CNode()<br />{<br />}</p><p>CNode::CNode(const CNode&amp; src)<br />{<br />  c_ = src.c_;<br />  r_ = src.r_;<br />  g_ = src.g_;<br />  h_ = src.h_;<br />  f_ = src.f_;<br />  parent_ = src.parent_;<br />}<br />&lt;/code&gt;</p><p>node.h<br />[code node.h]<br />#ifndef __NODE_H<br />#define __NODE_H</p><p>class CNode<br />{<br />  private:<br />  protected:<br />    int c_;<br />    int r_;<br />    int g_;<br />    int h_;<br />    int f_;<br />    const CNode* parent_;<br />  public:<br />    CNode(int c, int r, int g, int h, const CNode* parent = 0);<br />    virtual ~CNode();<br />    CNode(const CNode&amp; src);</p><p>    inline int get_c(void) const { return (c_); }<br />    inline int get_r(void) const { return (r_); }<br />    inline int get_g(void) const { return (g_); }<br />    inline int get_h(void) const { return (h_); }<br />    inline int get_f(void) const { return (f_); }<br />    inline const CNode* get_parent(void) const { return ((!parent_) ? this : parent_); }</p><p>    virtual bool operator &lt; (const CNode&amp; node) const { return (f_ &gt; node.f_); }<br />};</p><p>#endif<br />&lt;/code&gt;</p><p>(I will omit text.cpp and text.h because they aren&#39;t necessary)</p><p>I attached a picture of the problem. The yellow circle shows where the algo makes the mistake. IMO, the path should go straight down instead of doing a zigzag.</p><p>Finally, here is the map-file for this example:</p><p>map.map<br />[code map.map]<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00111111111111110000<br />00000000000000000000<br />00000000000000000000<br />00011111111111111111<br />00000000000000000000<br />00000000000000000000<br />00000000000000000000<br />00000011111111011111<br />00000010000000010000<br />00000010111111110000<br />00000010000000000000<br />3 3<br />16 17 1 1<br />&lt;/code&gt;</p><p>The first two numbers after the grid are the starting position in columns and rows and the second four are the position of the target (the two 1s don&#39;t have any meaning yet).</p><p>Thanks for your help! <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Thu, 26 Jan 2006 16:44:09 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Is the the minimum amount of code? Perhaps you could narrow it down to say a function that has the problem? Is it <tt>create_path</tt>? Explain what c, r, g, h, and f are.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Thu, 26 Jan 2006 17:35:01 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Is the the minimum amount of code?
</p></div></div><p>
Yes, I guess. If I took something out, I might have taken out the error too. <img src="http://www.allegro.cc/forums/smileys/sad.gif" alt=":(" /></p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Perhaps you could narrow it down to say a function that has the problem? Is it create_path?
</p></div></div><p>
Most likely! Or one of the functions it calls like get_best_f() or get_h(). I think the error is somewhere within the heuristic, but I dunno.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Explain what c, r, g, h, and f are.
</p></div></div><p>
Well, c and r are the column and the row of the node. g, h and f are the values used by every normal A* algorithm:<br />g - cost to move from the start to this node<br />h - cost to move from this node to the end (heuristic)<br />f - g + h (determines which node to take next)</p><p>I know it&#39;s not very easy. <img src="http://www.allegro.cc/forums/smileys/sad.gif" alt=":(" /> I needed to post all the code, because in most cases, it works correct, but only in very rare cases (as this one) it doesn&#39;t.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Thu, 26 Jan 2006 17:45:10 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Looks to me like you can only create unidirectional paths with your method. Why aren&#39;t nodes stored as a graph where the links contain the g, h, and f?</p><p>[edit]<br />Added a negative.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Thu, 26 Jan 2006 17:55:11 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Looks to me like you can only create unidirectional paths with your method.
</p></div></div><p>
But there is a horizontal path in there as well! I changed the g-value to 14 instead of ten for all diagonal movements exactly like [url <a href="http://www.policyalmanac.org/games/aStarTutorial.htm">http://www.policyalmanac.org/games/aStarTutorial.htm</a><br />]this tutorial[/url] suggested. <img src="http://www.allegro.cc/forums/smileys/huh.gif" alt="???" /></p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Why aren&#39;t nodes stored as a graph where the links contain the g, h, and f?
</p></div></div><p>
Could you explain that a bit more in detail? I don&#39;t know what you are talking about right now. <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Thu, 26 Jan 2006 18:21:58 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>No, unidirectional as in point A to B, and not point B to C or even point B to A (though the latter could be accomplished by traversing the lsit backwards).</p><p>What I mean is having each node store a list of Link structures. Each Link structure holds a Node that can be directly reached from its node, as well as the g, f, and h. This way simply coat the level with nodes and then move between them. They don&#39;t have to be on every tile. For instance:
</p><pre>00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
02000000000000000000
02111111111111112000
00200000000000020000
00020000000000000000
00211111111111111111
00000000000000000000
00000000000000000000
00000020000002000000
00000011111111211111
00000010200002010000
00000012111111110000
00000010200000020000</pre><p>The 2s are nodes, and the character simply moves in a straight line between them.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Thu, 26 Jan 2006 18:54:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Oh sorry, I missunderstood you!</p><p>Your approach is not A*, but it seems to be more like raycasting. I want the A*-way. The units shouldn&#39;t be able to move between nodes that are not adjacent to each other in one step.</p><p>I hope you understood me now.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Thu, 26 Jan 2006 19:49:56 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>No, my method is A*, you just don&#39;t use a grid. A* is simply using weighted steps to compute a path along a graph. A graph is just a bunch of locations that are connected.</p><p>The way you have it now, every square is a node, and every node is connected to its 8 adjacent nodes. Every connection has a weight of 1, because it takes the same amount of time to move to any square.</p><p>The way I suggest, you only place nodes at important places (corners), and the weight of each connection equals the distance.</p><p>Perhaps a better way to demonstrate what I mean is: Use your code to find a route from A to B, then from B to C, then from C to B.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Thu, 26 Jan 2006 22:01:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>It looks as if g was not taken into account, making diagonal movement as fast as  straight horizontal/vertical one.<br />Could you try to make run a straight north-south line? if it zigzags, you got your problem narrowed down.</p><p>Then try putting an absurdly high value of g for diagonal movement, to &quot;forbid&quot; it, and run your original problem: if the algorithm uses ANY diagonal, your code definitely doesn&#39;t take g into account.</p><p>edit: (heuristic from above) :
</p><div class="source-code snippet"><div class="inner"><pre><span class="c">//return (static_cast&lt;int&gt;(fabs(sqrt(pow(delta_x, 2) + pow(delta_y, 2)) * 10.0f)));</span>
  <span class="k1">return</span> <span class="k2">(</span><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_38.html" target="_blank">abs</a><span class="k2">(</span>ac <span class="k3">-</span> bc<span class="k2">)</span> <span class="k3">+</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_38.html" target="_blank">abs</a><span class="k2">(</span>ar <span class="k3">-</span> br<span class="k2">)</span><span class="k2">)</span> <span class="k3">*</span> <span class="n">10</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
Your heuristic expects diagonal movement to be as fast as horizontal one. So it takes the x+1 step getting closer (from a large perspective) to the final goal, as a future step will be able to take it (at no cost) off this dead-end.<br />Since your actual step costs are 10 and 14, you need a heuristic which weights 10 * min(abs(delta_x), abs(delta_y)) + 14 * abs(abs(delta_x) - abs(delta_y))
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Thu, 26 Jan 2006 22:47:25 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Well, in his model diagonal movement <b>is</b> as fast as normal up/down movement.</p><p>[edit]<br />Now you&#39;re saying it isn&#39;t... Is that so?</p><p>[edit]<br />In the case that you don&#39;t want diagonal movement to be weighted more than straight, simply bias it towards moving in a straight line. Say moves which are in the same direction as the previous move come at a -5 cost, adjust to suit.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Thu, 26 Jan 2006 23:04:02 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>(see my edit above)
</p><div class="quote_container"><div class="title">imaxcs said:</div><div class="quote"><p>
I changed the g-value to 14 instead of ten for all diagonal movements
</p></div></div><p>
When I first saw the post, there was indeed already a bunch of g_modifier+=4 in 4 of 8 direction cases, (an edit probably)
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Thu, 26 Jan 2006 23:07:30 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I have an update on my problem. It seems like my algorithm has problems with concave obstacles (see attached). The path leads slightly in the concave structure, then out again, but it should really go around it. As you see in the screenshot, it doesn&#39;t matter whether it is horizontal, vertical or diagonal, so this shouldn&#39;t be the error.</p><p>I am pretty sure the error lies in the create_path-function, so here is the shortened, wrapped in a class, path-finding-algo:</p><p>ac - start-column<br />ar - start-row<br />bc - end-column<br />br - end-row</p><p>path.h
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="p">#ifndef __PATH_H</span></td></tr><tr><td class="number">2</td><td><span class="p">#define __PATH_H</span></td></tr><tr><td class="number">3</td><td>&#160;</td></tr><tr><td class="number">4</td><td><span class="p">#include &lt;deque&gt;</span></td></tr><tr><td class="number">5</td><td><span class="p">#include &lt;list&gt;</span></td></tr><tr><td class="number">6</td><td><span class="p">#include &lt;iostream&gt;</span></td></tr><tr><td class="number">7</td><td><span class="p">#include &lt;algorithm&gt;</span></td></tr><tr><td class="number">8</td><td><span class="p">#include &lt;vector&gt;</span></td></tr><tr><td class="number">9</td><td>&#160;</td></tr><tr><td class="number">10</td><td><span class="p">#include "node.h"</span></td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td><span class="k1">using</span> std::deque<span class="k2">;</span></td></tr><tr><td class="number">13</td><td><span class="k1">using</span> std::list<span class="k2">;</span></td></tr><tr><td class="number">14</td><td><span class="k1">using</span> std::cout<span class="k2">;</span></td></tr><tr><td class="number">15</td><td><span class="k1">using</span> std::endl<span class="k2">;</span></td></tr><tr><td class="number">16</td><td><span class="k1">using</span> std::cin<span class="k2">;</span></td></tr><tr><td class="number">17</td><td><span class="k1">using</span> std::random_shuffle<span class="k2">;</span></td></tr><tr><td class="number">18</td><td><span class="k1">using</span> std::vector<span class="k2">;</span></td></tr><tr><td class="number">19</td><td>&#160;</td></tr><tr><td class="number">20</td><td><span class="k1">class</span> CPath</td></tr><tr><td class="number">21</td><td><span class="k2">{</span></td></tr><tr><td class="number">22</td><td>  private:</td></tr><tr><td class="number">23</td><td>    <span class="k1">const</span> <span class="k1">static</span> <span class="k1">int</span> MAX_NODE_CHECKS <span class="k3">=</span> <span class="n">1000</span><span class="k2">;</span></td></tr><tr><td class="number">24</td><td>    <span class="k1">const</span> <span class="k1">static</span> <span class="k1">int</span> MAPSIZE <span class="k3">=</span> <span class="n">20</span><span class="k2">;</span></td></tr><tr><td class="number">25</td><td>  protected:</td></tr><tr><td class="number">26</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span> openlist<span class="k2">;</span></td></tr><tr><td class="number">27</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span> closedlist<span class="k2">;</span></td></tr><tr><td class="number">28</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span> path<span class="k2">;</span></td></tr><tr><td class="number">29</td><td>  public:</td></tr><tr><td class="number">30</td><td>    <span class="k1">inline</span> CPath<span class="k2">(</span><span class="k2">)</span> <span class="k2">{</span><span class="k2">}</span></td></tr><tr><td class="number">31</td><td>    <span class="k1">inline</span> <span class="k1">virtual</span> ~CPath<span class="k2">(</span><span class="k2">)</span> <span class="k2">{</span><span class="k2">}</span></td></tr><tr><td class="number">32</td><td>    <span class="k1">inline</span> CPath<span class="k2">(</span><span class="k1">const</span> CPath<span class="k3">&amp;</span> src<span class="k2">)</span> <span class="k2">{</span><span class="k2">}</span></td></tr><tr><td class="number">33</td><td>&#160;</td></tr><tr><td class="number">34</td><td>    <span class="k1">int</span> get_h<span class="k2">(</span><span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">35</td><td>    <span class="k1">int</span> get_g<span class="k2">(</span><span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">36</td><td>    <span class="k1">bool</span> node_valid<span class="k2">(</span><span class="k1">int</span> c, <span class="k1">int</span> r<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">37</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator node_in_list<span class="k2">(</span><span class="k1">int</span> c, <span class="k1">int</span> r, list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">38</td><td>    <span class="k1">void</span> delete_list<span class="k2">(</span>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">39</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator get_best_f<span class="k2">(</span>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">40</td><td>    <span class="k1">bool</span> create_path<span class="k2">(</span><span class="k1">const</span> vector<span class="k3">&lt;</span> vector<span class="k3">&lt;</span>char&gt; <span class="k3">&gt;</span><span class="k3">&amp;</span> map, <span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br, <span class="k1">int</span> bw, <span class="k1">int</span> bh<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">41</td><td>&#160;</td></tr><tr><td class="number">42</td><td>    <span class="k1">void</span> clear<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">43</td><td>&#160;</td></tr><tr><td class="number">44</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_path_begin<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>path.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">45</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_path_end<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>path.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">46</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_openlist_begin<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>openlist.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">47</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_openlist_end<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>openlist.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">48</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_closedlist_begin<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>closedlist.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">49</td><td>    <span class="k1">inline</span> list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>const_iterator get_closedlist_end<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span> <span class="k1">const</span> <span class="k2">{</span> <span class="k1">return</span> <span class="k2">(</span>closedlist.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span> <span class="k2">}</span></td></tr><tr><td class="number">50</td><td><span class="k2">}</span><span class="k2">;</span></td></tr><tr><td class="number">51</td><td>&#160;</td></tr><tr><td class="number">52</td><td><span class="p">#endif</span></td></tr></tbody></table></div></div><p>


path.cpp
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="p">#include "path.h"</span></td></tr><tr><td class="number">2</td><td>&#160;</td></tr><tr><td class="number">3</td><td><span class="k1">int</span> CPath::get_h<span class="k2">(</span><span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br<span class="k2">)</span></td></tr><tr><td class="number">4</td><td><span class="k2">{</span></td></tr><tr><td class="number">5</td><td>  <span class="k1">int</span> delta_x <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_38.html" target="_blank">abs</a><span class="k2">(</span>ac <span class="k3">-</span> bc<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td>  <span class="k1">int</span> delta_y <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_38.html" target="_blank">abs</a><span class="k2">(</span>ar <span class="k3">-</span> br<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">7</td><td>  <span class="k1">return</span> <span class="k2">(</span><span class="k1">static_cast</span><span class="k3">&lt;</span>int&gt;<span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_738.html" target="_blank">sqrt</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_618.html" target="_blank">pow</a><span class="k2">(</span>delta_x, <span class="n">2</span><span class="k2">)</span> <span class="k3">+</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_618.html" target="_blank">pow</a><span class="k2">(</span>delta_y, <span class="n">2</span><span class="k2">)</span><span class="k2">)</span> <span class="k3">*</span> <span class="n">10</span>.<span class="n">0f</span><span class="k2">)</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">8</td><td>  <span class="c">//return ((abs(ac - bc) + abs(ar - br)) * 10);</span></td></tr><tr><td class="number">9</td><td><span class="k2">}</span></td></tr><tr><td class="number">10</td><td>&#160;</td></tr><tr><td class="number">11</td><td><span class="k1">int</span> CPath::get_g<span class="k2">(</span><span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br<span class="k2">)</span></td></tr><tr><td class="number">12</td><td><span class="k2">{</span></td></tr><tr><td class="number">13</td><td>  <span class="k1">int</span> g <span class="k3">=</span> <span class="n">10</span><span class="k2">;</span></td></tr><tr><td class="number">14</td><td>&#160;</td></tr><tr><td class="number">15</td><td>  <span class="k1">if</span> <span class="k2">(</span>ac <span class="k3">!</span><span class="k3">=</span> bc <span class="k3">&amp;</span><span class="k3">&amp;</span> ar <span class="k3">!</span><span class="k3">=</span> br<span class="k2">)</span></td></tr><tr><td class="number">16</td><td>    g <span class="k3">+</span><span class="k3">=</span> <span class="n">4</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>&#160;</td></tr><tr><td class="number">18</td><td>  <span class="k1">return</span> g<span class="k2">;</span></td></tr><tr><td class="number">19</td><td><span class="k2">}</span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td><span class="k1">bool</span> CPath::node_valid<span class="k2">(</span><span class="k1">int</span> c, <span class="k1">int</span> r<span class="k2">)</span></td></tr><tr><td class="number">22</td><td><span class="k2">{</span></td></tr><tr><td class="number">23</td><td>  <span class="k1">if</span> <span class="k2">(</span>c <span class="k3">&gt;</span> MAPSIZE <span class="k3">-</span> <span class="n">1</span> <span class="k3">|</span><span class="k3">|</span> c <span class="k3">&lt;</span> <span class="n">0</span> <span class="k3">|</span><span class="k3">|</span> r <span class="k3">&gt;</span> MAPSIZE <span class="k3">-</span> <span class="n">1</span> <span class="k3">|</span><span class="k3">|</span> c <span class="k3">&lt;</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">24</td><td>    <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">25</td><td>  <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">26</td><td><span class="k2">}</span></td></tr><tr><td class="number">27</td><td>&#160;</td></tr><tr><td class="number">28</td><td>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator CPath::node_in_list<span class="k2">(</span><span class="k1">int</span> c, <span class="k1">int</span> r, list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span></td></tr><tr><td class="number">29</td><td><span class="k2">{</span></td></tr><tr><td class="number">30</td><td>  list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator it <span class="k3">=</span> list_.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">31</td><td>  <span class="k1">while</span><span class="k2">(</span>it <span class="k3">!</span><span class="k3">=</span> list_.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">32</td><td>  <span class="k2">{</span></td></tr><tr><td class="number">33</td><td>    <span class="k1">if</span> <span class="k2">(</span><span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_c<span class="k2">(</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> c <span class="k3">&amp;</span><span class="k3">&amp;</span> <span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_r<span class="k2">(</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> r<span class="k2">)</span></td></tr><tr><td class="number">34</td><td>      <span class="k1">return</span> it<span class="k2">;</span></td></tr><tr><td class="number">35</td><td>    <span class="k3">*</span>it<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">36</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">37</td><td>  <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">38</td><td><span class="k2">}</span></td></tr><tr><td class="number">39</td><td>&#160;</td></tr><tr><td class="number">40</td><td><span class="k1">void</span> CPath::delete_list<span class="k2">(</span>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span></td></tr><tr><td class="number">41</td><td><span class="k2">{</span></td></tr><tr><td class="number">42</td><td>  list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator it <span class="k3">=</span> list_.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">43</td><td>  <span class="k1">while</span><span class="k2">(</span>it <span class="k3">!</span><span class="k3">=</span> list_.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">44</td><td>    <span class="k1">delete</span> <span class="k3">*</span>it<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">45</td><td><span class="k2">}</span></td></tr><tr><td class="number">46</td><td>&#160;</td></tr><tr><td class="number">47</td><td>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator CPath::get_best_f<span class="k2">(</span>list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k3">&amp;</span> list_<span class="k2">)</span></td></tr><tr><td class="number">48</td><td><span class="k2">{</span></td></tr><tr><td class="number">49</td><td>  list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator best <span class="k3">=</span> list_.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">50</td><td>  list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator it <span class="k3">=</span> list_.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">51</td><td>  <span class="k1">while</span><span class="k2">(</span>it <span class="k3">!</span><span class="k3">=</span> list_.end<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">52</td><td>  <span class="k2">{</span></td></tr><tr><td class="number">53</td><td>    <span class="k1">if</span> <span class="k2">(</span><span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_f<span class="k2">(</span><span class="k2">)</span> <span class="k3">&lt;</span> <span class="k2">(</span><span class="k3">*</span>best<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_f<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">54</td><td>      best <span class="k3">=</span> it<span class="k2">;</span></td></tr><tr><td class="number">55</td><td>    it<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">56</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">57</td><td>  <span class="k1">return</span> best<span class="k2">;</span></td></tr><tr><td class="number">58</td><td><span class="k2">}</span></td></tr><tr><td class="number">59</td><td>&#160;</td></tr><tr><td class="number">60</td><td><span class="k1">bool</span> CPath::create_path<span class="k2">(</span><span class="k1">const</span> vector<span class="k3">&lt;</span> vector<span class="k3">&lt;</span>char&gt; <span class="k3">&gt;</span><span class="k3">&amp;</span> map, <span class="k1">int</span> ac, <span class="k1">int</span> ar, <span class="k1">int</span> bc, <span class="k1">int</span> br, <span class="k1">int</span> bw, <span class="k1">int</span> bh<span class="k2">)</span></td></tr><tr><td class="number">61</td><td><span class="k2">{</span></td></tr><tr><td class="number">62</td><td>&#160;</td></tr><tr><td class="number">63</td><td>  <span class="c">// see, if we can return immediately</span></td></tr><tr><td class="number">64</td><td>  <span class="k1">if</span> <span class="k2">(</span>ac <span class="k3">=</span><span class="k3">=</span> bc <span class="k3">&amp;</span><span class="k3">&amp;</span> ar <span class="k3">=</span><span class="k3">=</span> br<span class="k2">)</span></td></tr><tr><td class="number">65</td><td>    <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">66</td><td>&#160;</td></tr><tr><td class="number">67</td><td>  <span class="c">// add the current node to the closedlist</span></td></tr><tr><td class="number">68</td><td>  openlist.push_front<span class="k2">(</span><span class="k1">new</span> CNode<span class="k2">(</span>ac, ar, <span class="n">0</span>, get_h<span class="k2">(</span>ac, ar, bc, br<span class="k2">)</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">69</td><td>&#160;</td></tr><tr><td class="number">70</td><td>  <span class="c">// create a target-node ( not in one of the lists ), so we can use target_reached() more easily</span></td></tr><tr><td class="number">71</td><td>  <span class="c">//const CNode* tar = new CNode(target-&gt;get_c(), target-&gt;get_r(), 0, 0);</span></td></tr><tr><td class="number">72</td><td>&#160;</td></tr><tr><td class="number">73</td><td>  <span class="c">// set the current node, which will be altered during the walk through the map</span></td></tr><tr><td class="number">74</td><td>  <span class="k1">const</span> CNode<span class="k3">*</span> cur <span class="k3">=</span> openlist.front<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">75</td><td>&#160;</td></tr><tr><td class="number">76</td><td>  <span class="k1">while</span><span class="k2">(</span>cur-&gt;get_c<span class="k2">(</span><span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> bc <span class="k3">|</span><span class="k3">|</span> cur-&gt;get_r<span class="k2">(</span><span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> br<span class="k2">)</span></td></tr><tr><td class="number">77</td><td>  <span class="k2">{</span></td></tr><tr><td class="number">78</td><td>    <span class="k1">int</span> c, r<span class="k2">;</span></td></tr><tr><td class="number">79</td><td>    <span class="k1">int</span> i<span class="k2">;</span></td></tr><tr><td class="number">80</td><td>&#160;</td></tr><tr><td class="number">81</td><td>    <span class="c">// check, if the openlist is empty or the closedlist too full</span></td></tr><tr><td class="number">82</td><td>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>openlist.size<span class="k2">(</span><span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span> <span class="k1">int</span><span class="k2">(</span>closedlist.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span> <span class="k3">&gt;</span> MAX_NODE_CHECKS<span class="k2">)</span></td></tr><tr><td class="number">83</td><td>      <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">84</td><td>&#160;</td></tr><tr><td class="number">85</td><td>    <span class="c">// put the node with the best f-value in the closedlist</span></td></tr><tr><td class="number">86</td><td>    list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator best_f <span class="k3">=</span> get_best_f<span class="k2">(</span>openlist<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">87</td><td>    closedlist.push_front<span class="k2">(</span><span class="k3">*</span>best_f<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">88</td><td>    openlist.erase<span class="k2">(</span>best_f<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">89</td><td>&#160;</td></tr><tr><td class="number">90</td><td>    <span class="c">// change the cur-variable</span></td></tr><tr><td class="number">91</td><td>    cur <span class="k3">=</span> <span class="k3">*</span>best_f<span class="k2">;</span></td></tr><tr><td class="number">92</td><td>&#160;</td></tr><tr><td class="number">93</td><td>    <span class="c">// add the surrounding nodes to the openlist</span></td></tr><tr><td class="number">94</td><td>    <span class="k1">for</span><span class="k2">(</span>i <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>i <span class="k3">&lt;</span> <span class="n">8</span><span class="k2">;</span>i<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span></td></tr><tr><td class="number">95</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">96</td><td>      c <span class="k3">=</span> cur-&gt;get_c<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">97</td><td>      r <span class="k3">=</span> cur-&gt;get_r<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">98</td><td>&#160;</td></tr><tr><td class="number">99</td><td>      <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">100</td><td>        c<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">101</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">1</span><span class="k2">)</span></td></tr><tr><td class="number">102</td><td>        c--<span class="k2">;</span></td></tr><tr><td class="number">103</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">2</span><span class="k2">)</span></td></tr><tr><td class="number">104</td><td>        r<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">105</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">3</span><span class="k2">)</span></td></tr><tr><td class="number">106</td><td>        r--<span class="k2">;</span></td></tr><tr><td class="number">107</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">4</span><span class="k2">)</span></td></tr><tr><td class="number">108</td><td>      <span class="k2">{</span></td></tr><tr><td class="number">109</td><td>        c<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">110</td><td>        r<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">111</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">112</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">5</span><span class="k2">)</span></td></tr><tr><td class="number">113</td><td>      <span class="k2">{</span></td></tr><tr><td class="number">114</td><td>        c--<span class="k2">;</span></td></tr><tr><td class="number">115</td><td>        r<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">116</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">117</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">6</span><span class="k2">)</span></td></tr><tr><td class="number">118</td><td>      <span class="k2">{</span></td></tr><tr><td class="number">119</td><td>        r--<span class="k2">;</span></td></tr><tr><td class="number">120</td><td>        c<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">121</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">122</td><td>      <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span>i <span class="k3">=</span><span class="k3">=</span> <span class="n">7</span><span class="k2">)</span></td></tr><tr><td class="number">123</td><td>      <span class="k2">{</span></td></tr><tr><td class="number">124</td><td>        r--<span class="k2">;</span></td></tr><tr><td class="number">125</td><td>        c--<span class="k2">;</span></td></tr><tr><td class="number">126</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">127</td><td>&#160;</td></tr><tr><td class="number">128</td><td>      <span class="k1">int</span> g <span class="k3">=</span> get_g<span class="k2">(</span>cur-&gt;get_c<span class="k2">(</span><span class="k2">)</span>, cur-&gt;get_r<span class="k2">(</span><span class="k2">)</span>, c, r<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">129</td><td>&#160;</td></tr><tr><td class="number">130</td><td>      <span class="k1">if</span> <span class="k2">(</span>node_valid<span class="k2">(</span>c, r<span class="k2">)</span> <span class="k3">&amp;</span><span class="k3">&amp;</span> map<span class="k2">[</span>c<span class="k2">]</span><span class="k2">[</span>r<span class="k2">]</span> <span class="k3">!</span><span class="k3">=</span> <span class="s">'1'</span> <span class="k3">&amp;</span><span class="k3">&amp;</span> node_in_list<span class="k2">(</span>c, r, closedlist<span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">131</td><td>      <span class="k2">{</span></td></tr><tr><td class="number">132</td><td>        list<span class="k3">&lt;</span>CNode<span class="k3">*</span><span class="k3">&gt;</span><span class="k2">:</span><span class="k2">:</span>iterator node_in_openlist <span class="k3">=</span> node_in_list<span class="k2">(</span>c, r, openlist<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">133</td><td>        <span class="k1">if</span> <span class="k2">(</span>node_in_openlist <span class="k3">=</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">134</td><td>          openlist.push_front<span class="k2">(</span><span class="k1">new</span> CNode<span class="k2">(</span>c, r, cur-&gt;get_g<span class="k2">(</span><span class="k2">)</span> <span class="k3">+</span> g, get_h<span class="k2">(</span>c, r, bc, br<span class="k2">)</span>, cur<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">135</td><td>        <span class="k1">else</span> <span class="k1">if</span> <span class="k2">(</span><span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_parent<span class="k2">(</span><span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_g<span class="k2">(</span><span class="k2">)</span> <span class="k3">&gt;</span> cur-&gt;get_g<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">136</td><td>        <span class="k2">{</span></td></tr><tr><td class="number">137</td><td>          <span class="k1">int</span> g <span class="k3">=</span> get_g<span class="k2">(</span>cur-&gt;get_c<span class="k2">(</span><span class="k2">)</span>, cur-&gt;get_r<span class="k2">(</span><span class="k2">)</span>, <span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_g<span class="k2">(</span><span class="k2">)</span>, <span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>get_g<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">138</td><td>&#160;</td></tr><tr><td class="number">139</td><td>          <span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>set_parent<span class="k2">(</span>cur<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">140</td><td>          <span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>set_g<span class="k2">(</span>cur-&gt;get_g<span class="k2">(</span><span class="k2">)</span> <span class="k3">+</span> g<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">141</td><td>          <span class="k2">(</span><span class="k3">*</span>node_in_openlist<span class="k2">)</span><span class="k3">-</span><span class="k3">&gt;</span>recalculate_f<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">142</td><td>        <span class="k2">}</span></td></tr><tr><td class="number">143</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">144</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">145</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">146</td><td>&#160;</td></tr><tr><td class="number">147</td><td>  <span class="c">// coming here, it means that there is a valid path</span></td></tr><tr><td class="number">148</td><td>  <span class="c">// now track back the way to the start by accessing the parent and save it in the path-variable</span></td></tr><tr><td class="number">149</td><td>  <span class="k1">while</span><span class="k2">(</span>cur <span class="k3">!</span><span class="k3">=</span> closedlist.back<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">150</td><td>  <span class="k2">{</span> <span class="c">// while start not reached</span></td></tr><tr><td class="number">151</td><td>    path.push_back<span class="k2">(</span><span class="k1">new</span> CNode<span class="k2">(</span><span class="k3">*</span>cur<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">152</td><td>    cur <span class="k3">=</span> cur-&gt;get_parent<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">153</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">154</td><td>&#160;</td></tr><tr><td class="number">155</td><td>  <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">156</td><td><span class="k2">}</span></td></tr><tr><td class="number">157</td><td>&#160;</td></tr><tr><td class="number">158</td><td><span class="k1">void</span> CPath::clear<span class="k2">(</span><span class="k1">void</span><span class="k2">)</span></td></tr><tr><td class="number">159</td><td><span class="k2">{</span></td></tr><tr><td class="number">160</td><td>  delete_list<span class="k2">(</span>path<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">161</td><td>  delete_list<span class="k2">(</span>openlist<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">162</td><td>  delete_list<span class="k2">(</span>closedlist<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">163</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

I hope this makes it easier for you to help me with my problem.</p><p>Thanks! <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Fri, 27 Jan 2006 19:48:51 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Well, it seems the diagonal moves are still not considered significantly more costly than straight moves. Any change if g = 15 for them (instead of g = 14) ? or g = 20? or g = 100 ?<br />Even 14 is an approximation of sqrt(2)/2*10 after all.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Fri, 27 Jan 2006 20:23:30 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I attached the map with g = 20!<br />The path is now correct, but it takes so much more time to calculate, which can&#39;t be right. <img src="http://www.allegro.cc/forums/smileys/sad.gif" alt=":(" /></p><p>edit: and g = 15 is approximately the same as 14.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Fri, 27 Jan 2006 21:16:42 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Lot&#39;s of source code to go through. Create an animation much as you have done your screenshots. Show a frame for each iteration in the loop you have in create_path, so that you visually can see how the algorithm works.</p><p>Perhaps the most likely problem is that you are checking nodes which wouldn&#39;t need to be checked? In that case you will see it immediately if you do the above for debug purposes.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (kentl)</author>
		<pubDate>Fri, 27 Jan 2006 22:04:52 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I think I&#39;m stuck there, sorry. The g h and f values on the graph should be enough for someone experienced with A* to troubleshoot further, but I&#39;m not one <img src="http://www.allegro.cc/forums/smileys/sad.gif" alt=":(" /></p><p>edit:<br /><a href="http://www.policyalmanac.org/games/aStarTutorial.htm">http://www.policyalmanac.org/games/aStarTutorial.htm</a>
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
(heuristic)... slightly overestimates the remaining distance (...) On the rare occasion when the resulting path is not the shortest possible, it will be nearly as short
</p></div></div><p>
<a href="http://www.policyalmanac.org/games/heuristics.htm">http://www.policyalmanac.org/games/heuristics.htm</a><br />I made you reinvent the wheel.<br />Today&#39;s lesson: When in doubt, ask google.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Fri, 27 Jan 2006 22:31:01 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I will look into your suggestions, thanks! <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (imaxcs)</author>
		<pubDate>Sat, 28 Jan 2006 01:44:45 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Have you tried using another metric (weight function, or whatever the name is in graph theory) weigh the edges? Right now, you&#39;re using <img class="math" src="http://www.allegro.cc/images/tex/3/e/3eb8a3a13e8496f597a9eca70349732a-96.png" alt="&lt;math&gt;\left|x\right| + \left|y\right|&lt;/math&gt;" />; try using <img class="math" src="http://www.allegro.cc/images/tex/a/e/ae18f520703656d100ae9049e756abff-96.png" alt="&lt;math&gt;x^2 + y^2&lt;/math&gt;" /> instead and see if that helps.</p><p>I&#39;m not sure if it will; from the description of the problem it sounds like nodes aren&#39;t properly recalculated or updated when you backtrack through the closed list, but I haven&#39;t looked at your code in detail. I also haven&#39;t touched my own in several years, so I&#39;m probably a bit rusty on the details.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Evert)</author>
		<pubDate>Sat, 28 Jan 2006 01:54:03 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I don&#39;t know A* but I&#39;ve implemented a path finder like yours, only I never implemented diagonal movements. Do you have trouble with your code or with your algorithm? Or do you want us to find out that?</p><p>My algo checks every single possible cell recursively, which takes time, but the result is the shortest path.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Johan Halmén)</author>
		<pubDate>Sat, 28 Jan 2006 02:23:08 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I have tried A-star a long time ago (2003) in Aether, We used the manhattan distance formula and it worked great. I tried other methods but it seems that this one was optimal for our game which uses 8 directions. You could try visiting this site for more information.</p><p><a href="http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S8">http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S8</a></p><p>Hope this helps. <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Homer Cuevas)</author>
		<pubDate>Sat, 28 Jan 2006 08:26:57 +0000</pubDate>
	</item>
</rss>
