Author: silene
Date: Fri May  1 17:19:22 2009
New Revision: 35380

URL: http://svn.gna.org/viewcvs/wesnoth?rev=35380&view=rev
Log:
Improved the pathfinder by making it touch only the visited nodes. Should 
noticeably speed up the AI.

Modified:
    trunk/src/pathfind.cpp

Modified: trunk/src/pathfind.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/pathfind.cpp?rev=35380&r1=35379&r2=35380&view=diff
==============================================================================
--- trunk/src/pathfind.cpp (original)
+++ trunk/src/pathfind.cpp Fri May  1 17:19:22 2009
@@ -104,22 +104,26 @@
        return false;
 }
 
+static unsigned search_counter;
+
 namespace {
+
 struct node {
        int movement_left, turns_left;
        map_location prev, curr;
-       bool in;
-               
-       node(int moves, int turns, map_location p, map_location c) : 
movement_left(moves), turns_left(turns), prev(p), curr(c), in(false) { }
-       node() : movement_left(-1), turns_left(-1), 
prev(map_location::null_location), curr(map_location::null_location), in(false) 
{ }
+
+       /**
+        * If equal to search_counter, the node is off the list.
+        * If equal to search_counter + 1, the node is on the list.
+        * Otherwise it is outdated.
+        */
+       unsigned in;
+
+       node(int moves, int turns, const map_location &p, const map_location &c)
+               : movement_left(moves), turns_left(turns), prev(p), curr(c) { }
+       node() : in(0) { }
        bool operator<(const node& o) const {
                return turns_left > o.turns_left || (turns_left == o.turns_left 
&& movement_left > o.movement_left);
-       }
-       bool operator>(const node& o) const {
-               return o < (*this);
-       }
-       bool operator<=(const node& o) const {
-               return !(o < (*this));
        }
 };
 
@@ -135,7 +139,7 @@
        const std::vector<node>& nodes;
        comp(const std::vector<node>& n) : nodes(n) { }
        bool operator()(int l, int r) const {
-               return nodes[l] > nodes[r];
+               return nodes[r] < nodes[l];
        }
 };
 }
@@ -155,14 +159,18 @@
        
        std::vector<map_location> locs(6 + teleports.size());
        std::copy(teleports.begin(), teleports.end(), locs.begin() + 6);
-       
+
+       search_counter += 2;
+       if (search_counter == 0) search_counter = 2;
+
        static std::vector<node> nodes;
-       nodes.clear();
        nodes.resize(map.w() * map.h());
        
        indexer index(map.w(), map.h());
        comp node_comp(nodes);
-       
+
+       int xmin = map.w(), xmax = 0, ymin = map.h(), ymax = 0;
+
        nodes[index(loc)] = node(move_left, turns_left, 
map_location::null_location, loc);
        std::vector<int> pq;
        pq.push_back(index(loc));
@@ -171,18 +179,20 @@
                node& n = nodes[pq.front()];
                std::pop_heap(pq.begin(), pq.end(), node_comp);
                pq.pop_back();
-               n.in = false;
+               n.in = search_counter;
                
                get_adjacent_tiles(n.curr, &locs[0]);
                for (int i = teleports.count(n.curr) ? locs.size() : 6; i-- > 
0; ) {
                        if (!locs[i].valid(map.w(), map.h())) continue;
                        
                        node& next = nodes[index(locs[i])];
-                       
+
+                       bool next_visited = next.in - search_counter <= 1u;
+
                        // test if the current path to locs[i] is better than 
this one could possibly be.
                        // we do this a couple more times below
-                       if (next <= n) continue;
-                       
+                       if (next_visited && !(n < next)) continue;
+
                        const int move_cost = u.movement_cost(map[locs[i]]);
                        
                        node t = node(n.movement_left, n.turns_left, n.curr, 
locs[i]);
@@ -194,9 +204,9 @@
                        if (t.movement_left < move_cost || t.turns_left < 0) 
continue;
                        
                        t.movement_left -= move_cost;
-                       
-                       if (next <= t) continue;
-                                               
+
+                       if (next_visited && !(t < next)) continue;
+
                        if (!ignore_units) {
                                const unit_map::const_iterator unit_it =
                                        find_visible_unit(units, locs[i], map, 
teams, viewing_team, see_all);
@@ -209,14 +219,21 @@
                                                && 
!u.get_ability_bool("skirmisher", locs[i])) {
                                        t.movement_left = 0;
                                }
-                               
-                               if (next <= t) continue;
+
+                               if (next_visited && !(t < next)) continue;
                        }
-                       
-                       bool in_list = next.in;
+
+                       int x = locs[i].x;
+                       if (x < xmin) xmin = x;
+                       if (xmax < x) xmax = x;
+                       int y = locs[i].y;
+                       if (y < ymin) ymin = y;
+                       if (ymax < y) ymax = y;
+
+                       bool in_list = next.in == search_counter + 1;
+                       t.in = search_counter + 1;
                        next = t;
-                       next.in = true;
-                       
+
                        // if already in the priority queue then we just update 
it, else push it.
                        if (in_list) {
                                std::push_heap(pq.begin(), 
std::find(pq.begin(), pq.end(), index(locs[i])) + 1, node_comp);
@@ -228,23 +245,29 @@
        }
        
        // build the routes for every map_location that we reached 
-       foreach(const node& n, nodes) {
-               if (n.movement_left < 0 || n.turns_left < 0) continue;
-               paths::route route;
-               route.move_left = n.movement_left + n.turns_left * 
total_movement;
-               
-               // the ai expects that the destination map_location not 
actually be in the route...
-               if (n.prev != map_location::null_location) {
-                       for (node curr = nodes[index(n.prev)]; curr.prev != 
map_location::null_location; curr = nodes[index(curr.prev)]) {
-                               assert(curr.curr != 
map_location::null_location);
-                               route.steps.push_back(curr.curr);
+       for (int y = ymin; y <= ymax; ++y) {
+               for (int x = xmin; x <= xmax; ++x)
+               {
+                       const node &n = nodes[index(map_location(x, y))];
+                       if (n.in - search_counter > 1u) continue;
+                       paths::route route;
+                       route.move_left = n.movement_left + n.turns_left * 
total_movement;
+
+                       // the ai expects that the destination map_location not 
actually be in the route...
+                       if (n.prev.valid())
+                       {
+                               for (const node *curr = &nodes[index(n.prev)];
+                                    curr->prev.valid(); curr = 
&nodes[index(curr->prev)])
+                               {
+                                       assert(curr->curr.valid());
+                                       route.steps.push_back(curr->curr);
+                               }
                        }
-               }
-               route.steps.push_back(loc);
-               std::reverse(route.steps.begin(), route.steps.end());   
-               
-               routes[n.curr] = route;         
-       }       
+                       route.steps.push_back(loc);
+                       std::reverse(route.steps.begin(), route.steps.end());
+                       routes[n.curr] = route;
+               }
+       }
 }
 
 paths::paths(gamemap const &map, unit_map const &units,


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to