wesnoth-cvs-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Wesnoth-cvs-commits] wesnoth/src actions.cpp ai.cpp ai_move.cpp cave...


From: Guillaume Melquiond
Subject: [Wesnoth-cvs-commits] wesnoth/src actions.cpp ai.cpp ai_move.cpp cave...
Date: Sun, 05 Dec 2004 17:20:50 -0500

CVSROOT:        /cvsroot/wesnoth
Module name:    wesnoth
Branch:         
Changes by:     Guillaume Melquiond <address@hidden>    04/12/05 22:14:30

Modified files:
        src            : actions.cpp ai.cpp ai_move.cpp cavegen.cpp 
                         game_events.cpp mapgen.cpp pathfind.cpp 
                         pathfind.hpp playturn.cpp 

Log message:
        Remove A* from the header and put it into a single object file. It 
reduces compile time, and it could speed up the AI.

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/actions.cpp.diff?tr1=1.171&tr2=1.172&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/ai.cpp.diff?tr1=1.127&tr2=1.128&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/ai_move.cpp.diff?tr1=1.52&tr2=1.53&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/cavegen.cpp.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/game_events.cpp.diff?tr1=1.115&tr2=1.116&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/mapgen.cpp.diff?tr1=1.46&tr2=1.47&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/pathfind.cpp.diff?tr1=1.47&tr2=1.48&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/pathfind.hpp.diff?tr1=1.33&tr2=1.34&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/playturn.cpp.diff?tr1=1.308&tr2=1.309&r1=text&r2=text

Patches:
Index: wesnoth/src/actions.cpp
diff -u wesnoth/src/actions.cpp:1.171 wesnoth/src/actions.cpp:1.172
--- wesnoth/src/actions.cpp:1.171       Sun Dec  5 18:37:36 2004
+++ wesnoth/src/actions.cpp     Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: actions.cpp,v 1.171 2004/12/05 18:37:36 silene Exp $ */
+/* $Id: actions.cpp,v 1.172 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -42,12 +42,12 @@
 #define LOG_NG lg::info(lg::engine)
 #define ERR_NW lg::err(lg::network)
 
-struct castle_cost_calculator
+struct castle_cost_calculator : cost_calculator
 {
        castle_cost_calculator(const gamemap& map) : map_(map)
        {}
 
-       double cost(const gamemap::location& loc, double cost_so_far) const
+       virtual double cost(const gamemap::location& loc, double) const
        {
                if(!map_.is_castle(loc))
                        return 10000;
@@ -104,8 +104,8 @@
        }
 
        if(need_castle && map.on_board(recruit_location)) {
-               const paths::route& rt = 
a_star_search(u->first,recruit_location,
-                                                  
100.0,castle_cost_calculator(map));
+               castle_cost_calculator calc(map);
+               const paths::route& rt = a_star_search(u->first, 
recruit_location, 100.0, &calc);
                if(rt.steps.empty() || units.find(recruit_location) != 
units.end() ||
                   !map.is_castle(recruit_location))
                        recruit_location = gamemap::location();
@@ -448,8 +448,8 @@
        if (strings && resist != 0) {
                std::stringstream str_resist;
                str_resist << gettext(resist < 0 ? N_("defender resistance vs") 
: N_("defender vulnerability vs"))
-                       << ' ' << gettext(attack.type().c_str()) << EMPTY_COLUMN
-                       << (resist > 0 ? "+" : "") << resist << '%';
+                          << ' ' << gettext(attack.type().c_str()) << 
EMPTY_COLUMN
+                          << (resist > 0 ? "+" : "") << resist << '%';
                strings->attack_calculations.push_back(str_resist.str());
        }
 
@@ -468,7 +468,7 @@
        if (under_leadership(units,attacker,&leader_bonus).valid()) {
                percent += leader_bonus;
                
-               if(strings) {
+               if (strings) {
                        std::stringstream str;
                        str << _("leadership") << EMPTY_COLUMN << '+' << 
leader_bonus << '%';
                        strings->attack_calculations.push_back(str.str());
Index: wesnoth/src/ai.cpp
diff -u wesnoth/src/ai.cpp:1.127 wesnoth/src/ai.cpp:1.128
--- wesnoth/src/ai.cpp:1.127    Sun Dec  5 18:37:36 2004
+++ wesnoth/src/ai.cpp  Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: ai.cpp,v 1.127 2004/12/05 18:37:36 silene Exp $ */
+/* $Id: ai.cpp,v 1.128 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -1504,7 +1504,7 @@
                const shortest_path_calculator 
calc(temp_unit,current_team(),units,teams_,map_,state_);
                for(std::vector<target>::const_iterator t = targets.begin(); t 
!= targets.end(); ++t) {
                        LOG_AI << "analyzing '" << *i << "' getting to 
target...\n";
-                       const paths::route& route = 
a_star_search(start,t->loc,100.0,calc);
+                       const paths::route& route = a_star_search(start, 
t->loc, 100.0, &calc);
                        if(route.steps.empty() == false) {
                                LOG_AI << "made it: " << route.move_left << 
"\n";
                                cost += route.move_left;
@@ -1651,7 +1651,8 @@
        
        do_recruitment();
 
-       const paths::route route = 
a_star_search(leader->first,dst,1000.0,shortest_path_calculator(leader->second,current_team(),units_,teams_,map_,state_));
+       shortest_path_calculator calc(leader->second, current_team(), units_, 
teams_, map_, state_);
+       const paths::route route = a_star_search(leader->first, dst, 1000.0, 
&calc);
        if(route.steps.empty()) {
                LOG_AI << "route empty";
                return;
Index: wesnoth/src/ai_move.cpp
diff -u wesnoth/src/ai_move.cpp:1.52 wesnoth/src/ai_move.cpp:1.53
--- wesnoth/src/ai_move.cpp:1.52        Thu Nov 18 22:00:12 2004
+++ wesnoth/src/ai_move.cpp     Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: ai_move.cpp,v 1.52 2004/11/18 22:00:12 ydirson Exp $ */
+/* $Id: ai_move.cpp,v 1.53 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -24,7 +24,7 @@
 
 #define LOG_AI lg::info(lg::ai)
 
-struct move_cost_calculator
+struct move_cost_calculator : cost_calculator
 {
        move_cost_calculator(const unit& u, const gamemap& map,
                             const game_data& data,
@@ -37,7 +37,7 @@
                avoid_enemies_(u.type().usage() == "scout")
        {}
 
-       double cost(const gamemap::location& loc, double so_far) const
+       virtual double cost(const gamemap::location& loc, double) const
        {
                if(!map_.on_board(loc))
                        return 1000.0;
@@ -425,7 +425,7 @@
 
                assert(map_.on_board(tg->loc));
                const paths::route cur_route = a_star_search(u->first,tg->loc,
-                                      
minimum(tg->value/best_rating,500.0),cost_calc);
+                                      minimum(tg->value/best_rating,500.0), 
&cost_calc);
 
                double rating = tg->value/maximum<int>(1,cur_route.move_left);
 
@@ -493,7 +493,7 @@
        
                        const move_cost_calculator 
calc(u->second,map_,gameinfo_,units_,u->first,dstsrc,enemy_dstsrc);
                        const paths::route cur_route = 
a_star_search(u->first,best_target->loc,
-                                              
minimum(best_target->value/best_rating,100.0),calc);
+                                              minimum(best_target->value / 
best_rating, 100.0), &calc);
                        double rating = 
best_target->value/maximum<int>(1,cur_route.move_left);
 
                        //for 'support' targets, they are rated much higher if 
we can get there within two turns,
@@ -742,7 +742,8 @@
        for(move_map::const_iterator i = locs.first; i != locs.second; ++i) {
                const location& loc = i->second;
                if(distance_between(loc,dst) <= u_it->second.total_movement()) {
-                       const paths::route& rt = 
a_star_search(loc,dst,u_it->second.total_movement(),shortest_path_calculator(u_it->second,current_team(),units_,teams_,map_,state_));
+                       shortest_path_calculator calc(u_it->second, 
current_team(), units_, teams_, map_, state_);
+                       const paths::route& rt = a_star_search(loc, dst, 
u_it->second.total_movement(), &calc);
                        if(rt.steps.empty() == false) {
                                out.push_back(loc);
                        }
Index: wesnoth/src/cavegen.cpp
diff -u wesnoth/src/cavegen.cpp:1.9 wesnoth/src/cavegen.cpp:1.10
--- wesnoth/src/cavegen.cpp:1.9 Thu Nov 18 04:08:32 2004
+++ wesnoth/src/cavegen.cpp     Sun Dec  5 22:14:29 2004
@@ -262,13 +262,13 @@
        }
 }
 
-struct passage_path_calculator
+struct passage_path_calculator : cost_calculator
 {
        passage_path_calculator(const std::vector<std::vector<gamemap::TERRAIN> 
>& mapdata, gamemap::TERRAIN wall, double laziness, size_t windiness)
                        : map_(mapdata), wall_(wall), laziness_(laziness), 
windiness_(windiness)
        {}
        
-       double cost(const gamemap::location& loc, double so_far) const;
+       virtual double cost(const gamemap::location& loc, double so_far) const;
 private:
        const std::vector<std::vector<gamemap::TERRAIN> >& map_;
        gamemap::TERRAIN wall_;
@@ -276,7 +276,7 @@
        size_t windiness_;
 };
 
-double passage_path_calculator::cost(const gamemap::location& loc, double 
so_far) const
+double passage_path_calculator::cost(const gamemap::location& loc, double) 
const
 {
        if(loc.x < 0 || loc.y < 0 || size_t(loc.x) >= map_.size() || 
map_.empty() || size_t(loc.y) >= map_.front().size()) {
                return 100000.0;
@@ -307,7 +307,7 @@
        
        passage_path_calculator calc(map_,wall_,laziness,windiness);
        
-       const paths::route rt = a_star_search(p.src,p.dst,10000.0,calc);
+       const paths::route rt = a_star_search(p.src, p.dst, 10000.0, &calc);
 
        const size_t width = maximum<size_t>(1,atoi(p.cfg["width"].c_str()));
        const size_t jagged = atoi(p.cfg["jagged"].c_str());
Index: wesnoth/src/game_events.cpp
diff -u wesnoth/src/game_events.cpp:1.115 wesnoth/src/game_events.cpp:1.116
--- wesnoth/src/game_events.cpp:1.115   Sat Dec  4 23:44:09 2004
+++ wesnoth/src/game_events.cpp Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: game_events.cpp,v 1.115 2004/12/04 23:44:09 isaaccp Exp $ */
+/* $Id: game_events.cpp,v 1.116 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -481,7 +481,7 @@
                                dst.x = atoi(xvals[i].c_str())-1;
                                dst.y = atoi(yvals[i].c_str())-1;
 
-                               paths::route 
route=a_star_search(src,dst,10000,calc,0);
+                               paths::route route=a_star_search(src, dst, 
10000, &calc, 0);
                                unit_display::move_unit(*screen, *game_map, 
route.steps,
                                                
dummy_unit,status_ptr->get_time_of_day(), *units, *teams);
 
Index: wesnoth/src/mapgen.cpp
diff -u wesnoth/src/mapgen.cpp:1.46 wesnoth/src/mapgen.cpp:1.47
--- wesnoth/src/mapgen.cpp:1.46 Thu Nov 18 04:08:32 2004
+++ wesnoth/src/mapgen.cpp      Sun Dec  5 22:14:29 2004
@@ -338,14 +338,14 @@
 
 //an object that will calculate the cost of building a road over terrain
 //for use in the a_star_search algorithm.
-struct road_path_calculator
+struct road_path_calculator : cost_calculator
 {
        road_path_calculator(const terrain_map& terrain, const config& cfg)
                        : calls(0), map_(terrain), cfg_(cfg),
 
                                  //find out how windy roads should be.
                                  
windiness_(maximum<int>(1,atoi(cfg["road_windiness"].c_str()))) {}
-       double cost(const location& loc, double so_far) const;
+       virtual double cost(const location& loc, double so_far) const;
 
        void terrain_changed(const location& loc) { loc_cache_.erase(loc); }
        mutable int calls;
@@ -357,7 +357,7 @@
        mutable std::map<char,double> cache_;
 };
 
-double road_path_calculator::cost(const location& loc, double so_far) const
+double road_path_calculator::cost(const location& loc, double) const
 {
        ++calls;
        if(loc.x < 0 || loc.y < 0 || loc.x >= map_.size() || loc.y >= 
map_.front().size())
@@ -394,17 +394,6 @@
        return windiness*res;
 }
 
-struct road_path_calculator_wrapper
-{
-       explicit road_path_calculator_wrapper(const road_path_calculator& calc) 
: calc_(&calc)
-       {}
-
-       double cost(const location& loc, double so_far) const { return 
calc_->cost(loc,so_far); }
-
-private:
-       const road_path_calculator* calc_;
-};
-
 struct is_valid_terrain
 {
        is_valid_terrain(const std::vector<std::vector<gamemap::TERRAIN> >& 
map, const std::string& terrain_list);
@@ -911,7 +900,6 @@
        std::set<location> bridges;
 
        road_path_calculator calc(terrain,cfg);
-       const road_path_calculator_wrapper calc_wrapper(calc);
        for(size_t road = 0; road != nroads; ++road) {
                log_scope("creating road");
 
@@ -947,7 +935,7 @@
                }
 
                //search a path out for the road
-               const paths::route rt = 
a_star_search(src,dst,10000.0,calc_wrapper);
+               const paths::route rt = a_star_search(src, dst, 10000.0, &calc);
 
                const std::string& name = 
generate_name(name_generator,"road_name");
                const int name_frequency = 20;
Index: wesnoth/src/pathfind.cpp
diff -u wesnoth/src/pathfind.cpp:1.47 wesnoth/src/pathfind.cpp:1.48
--- wesnoth/src/pathfind.cpp:1.47       Thu Nov 18 22:00:12 2004
+++ wesnoth/src/pathfind.cpp    Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: pathfind.cpp,v 1.47 2004/11/18 22:00:12 ydirson Exp $ */
+/* $Id: pathfind.cpp,v 1.48 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -14,12 +14,175 @@
 #include "global.hpp"
 
 #include "game.hpp"
+#include "log.hpp"
 #include "pathfind.hpp"
 #include "util.hpp"
 
 #include <cmath>
 #include <iostream>
-#include <set>
+
+#define LOG_PF lg::info(lg::engine)
+
+namespace {
+struct node {
+       static double heuristic(const gamemap::location& src,
+                               const gamemap::location& dst) {
+               return distance_between(src,dst);
+       }
+
+       node(const gamemap::location& pos, const gamemap::location& dst,
+               double cost, const gamemap::location& parent,
+            const std::set<gamemap::location>* teleports)
+           : loc(pos), parent(parent), g(cost), h(heuristic(pos,dst))
+       {
+
+               //if there are teleport locations, correct the heuristic to
+               //take them into account
+               if(teleports != NULL) {
+                       double srch = h, dsth = h;
+                       std::set<gamemap::location>::const_iterator i;
+                       for(i = teleports->begin(); i != teleports->end(); ++i) 
{
+                               const double new_srch = heuristic(pos,*i);
+                               const double new_dsth = heuristic(*i,dst);
+                               if(new_srch < srch) {
+                                       srch = new_srch;
+                               }
+
+                               if(new_dsth < dsth) {
+                                       dsth = new_dsth;
+                               }
+                       }
+
+                       if(srch + dsth + 1.0 < h) {
+                               h = srch + dsth + 1.0;
+                       }
+               }
+
+               f = g + h;
+       }
+
+       gamemap::location loc, parent;
+       double g, h, f;
+};
+
+}
+
+paths::route a_star_search(gamemap::location const &src, gamemap::location 
const &dst,
+                           double stop_at, cost_calculator const *obj,
+                           std::set<gamemap::location> const *teleports)
+{
+       LOG_PF << "a* search: " << src.x << ", " << src.y << " -> " << dst.x << 
", " << dst.y << "\n";
+       typedef gamemap::location location;
+
+       typedef std::map<location,node> list_map;
+       typedef std::pair<location,node> list_type;
+
+       std::multimap<double,location> open_list_ordered;
+       list_map open_list, closed_list;
+
+       open_list.insert(list_type(src,node(src,dst,0.0,location(),teleports)));
+       open_list_ordered.insert(std::pair<double,location>(0.0,src));
+
+       std::vector<location> locs;
+       while(!open_list.empty()) {
+
+               assert(open_list.size() == open_list_ordered.size());
+
+               const list_map::iterator lowest_in_open = 
open_list.find(open_list_ordered.begin()->second);
+               assert(lowest_in_open != open_list.end());
+
+               //move the lowest element from the open list to the closed list
+               closed_list.erase(lowest_in_open->first);
+               const list_map::iterator lowest = 
closed_list.insert(*lowest_in_open).first;
+
+               open_list.erase(lowest_in_open);
+               open_list_ordered.erase(open_list_ordered.begin());
+
+               //find nodes we can go to from this node
+               locs.resize(6);
+               get_adjacent_tiles(lowest->second.loc,&locs[0]);
+               if(teleports != NULL && teleports->count(lowest->second.loc) != 
0) {
+                       
std::copy(teleports->begin(),teleports->end(),std::back_inserter(locs));
+               }
+
+               for(size_t j = 0; j != locs.size(); ++j) {
+
+                       //if we have found a solution
+                       if(locs[j] == dst) {
+                               LOG_PF << "found solution; calculating it...\n";
+                               paths::route rt;
+
+                               for(location loc = lowest->second.loc; 
loc.valid(); ) {
+                                       rt.steps.push_back(loc);
+                                       list_map::const_iterator itor = 
open_list.find(loc);
+                                       if(itor == open_list.end()) {
+                                               itor = closed_list.find(loc);
+                                               assert(itor != 
closed_list.end());
+                                       }
+
+                                       loc = itor->second.parent;
+                               }
+                               
+                               std::reverse(rt.steps.begin(),rt.steps.end());
+                               rt.steps.push_back(dst);
+                               rt.move_left = int(lowest->second.g + 
obj->cost(dst,lowest->second.g));
+
+                               assert(rt.steps.front() == src);
+
+                               LOG_PF << "exiting a* search (solved)\n";
+
+                               return rt;
+                       }
+
+                       list_map::iterator current_best = 
open_list.find(locs[j]);
+                       const bool in_open = current_best != open_list.end();
+                       if(!in_open) {
+                               current_best = closed_list.find(locs[j]);
+                       }
+
+                       if(current_best != closed_list.end() && 
current_best->second.g <= lowest->second.g+1.0) {
+                               continue;
+                       }
+
+                       const double new_cost = 
obj->cost(locs[j],lowest->second.g);
+
+                       const node nd(locs[j],dst,lowest->second.g+new_cost,
+                                     lowest->second.loc,teleports);
+
+                       if(current_best != closed_list.end()) {
+                               if(current_best->second.g <= nd.g) {
+                                       continue;
+                               } else if(in_open) {
+                                       typedef 
std::multimap<double,location>::iterator Itor;
+                                       std::pair<Itor,Itor> itors = 
open_list_ordered.equal_range(current_best->second.f);
+                                       while(itors.first != itors.second) {
+                                               if(itors.first->second == 
current_best->second.loc) {
+                                                       
open_list_ordered.erase(itors.first);
+                                                       break;
+                                               }
+                                               ++itors.first;
+                                       }
+
+                                       open_list.erase(current_best);
+                               } else {
+                                       closed_list.erase(current_best);
+                               }
+                       }
+
+                       if(nd.f < stop_at) {
+                               open_list.insert(list_type(nd.loc,nd));
+                               
open_list_ordered.insert(std::pair<double,location>(nd.f,nd.loc));
+                       } else {
+                               closed_list.insert(list_type(nd.loc,nd));
+                       }
+               }
+       }
+
+       LOG_PF << "aborted a* search\n";
+       paths::route val;
+       val.move_left = 100000;
+       return val;
+}
 
 namespace {
 gamemap::location find_vacant(const gamemap& map,
Index: wesnoth/src/pathfind.hpp
diff -u wesnoth/src/pathfind.hpp:1.33 wesnoth/src/pathfind.hpp:1.34
--- wesnoth/src/pathfind.hpp:1.33       Sun Sep 19 11:13:56 2004
+++ wesnoth/src/pathfind.hpp    Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: pathfind.hpp,v 1.33 2004/09/19 11:13:56 silene Exp $ */
+/* $Id: pathfind.hpp,v 1.34 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -20,16 +20,11 @@
 #include "pathutils.hpp"
 #include "unit.hpp"
 
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <iostream>
 #include <map>
 #include <list>
+#include <set>
 #include <vector>
 
-#define LOG_PF lg::info(lg::engine)
-
 //this module contains various pathfinding functions and utilities.
 
 //a convenient type for storing a list of tiles adjacent to a certain tile
@@ -96,14 +91,18 @@
 int route_turns_to_complete(const unit& u, const gamemap& map,
                             const paths::route& rt);
 
-struct shortest_path_calculator
+struct cost_calculator
+{
+       virtual double cost(const gamemap::location& loc, double so_far) const 
= 0;
+       virtual ~cost_calculator() {}
+};
+
+struct shortest_path_calculator : cost_calculator
 {
        shortest_path_calculator(const unit& u, const team& t,
-                                const unit_map& units, 
-                                                                        const 
std::vector<team>& teams,
-                                                                        const 
gamemap& map,
-                                                                        const 
gamestatus& status);
-       double cost(const gamemap::location& loc, double so_far) const;
+                                const unit_map& units, const 
std::vector<team>& teams,
+                                const gamemap& map, const gamestatus& status);
+       virtual double cost(const gamemap::location& loc, double so_far) const;
 
 private:
        const unit& unit_;
@@ -114,169 +113,8 @@
        const gamestatus& status_;
 };
 
-namespace detail {
-struct node {
-       static double heuristic(const gamemap::location& src,
-                               const gamemap::location& dst) {
-               return distance_between(src,dst);
-       }
-
-       node(const gamemap::location& pos, const gamemap::location& dst,
-               double cost, const gamemap::location& parent,
-            const std::set<gamemap::location>* teleports)
-           : loc(pos), parent(parent), g(cost), h(heuristic(pos,dst))
-       {
-
-               //if there are teleport locations, correct the heuristic to
-               //take them into account
-               if(teleports != NULL) {
-                       double srch = h, dsth = h;
-                       std::set<gamemap::location>::const_iterator i;
-                       for(i = teleports->begin(); i != teleports->end(); ++i) 
{
-                               const double new_srch = heuristic(pos,*i);
-                               const double new_dsth = heuristic(*i,dst);
-                               if(new_srch < srch) {
-                                       srch = new_srch;
-                               }
-
-                               if(new_dsth < dsth) {
-                                       dsth = new_dsth;
-                               }
-                       }
-
-                       if(srch + dsth + 1.0 < h) {
-                               h = srch + dsth + 1.0;
-                       }
-               }
-
-               f = g + h;
-       }
-
-       gamemap::location loc, parent;
-       double g, h, f;
-};
-
-}
-
-template<typename T>
-paths::route a_star_search(const gamemap::location& src,
-                           const gamemap::location& dst, double stop_at, T obj,
-                           const std::set<gamemap::location>* teleports=NULL)
-{
-       LOG_PF << "a* search: " << src.x << ", " << src.y << " -> " << dst.x << 
", " << dst.y << "\n";
-       using namespace detail;
-       typedef gamemap::location location;
-
-       typedef std::map<location,node> list_map;
-       typedef std::pair<location,node> list_type;
-
-       std::multimap<double,location> open_list_ordered;
-       list_map open_list, closed_list;
-
-       open_list.insert(list_type(src,node(src,dst,0.0,location(),teleports)));
-       open_list_ordered.insert(std::pair<double,location>(0.0,src));
-
-       std::vector<location> locs;
-       while(!open_list.empty()) {
-
-               assert(open_list.size() == open_list_ordered.size());
-
-               const list_map::iterator lowest_in_open = 
open_list.find(open_list_ordered.begin()->second);
-               assert(lowest_in_open != open_list.end());
-
-               //move the lowest element from the open list to the closed list
-               closed_list.erase(lowest_in_open->first);
-               const list_map::iterator lowest = 
closed_list.insert(*lowest_in_open).first;
-
-               open_list.erase(lowest_in_open);
-               open_list_ordered.erase(open_list_ordered.begin());
-
-               //find nodes we can go to from this node
-               locs.resize(6);
-               get_adjacent_tiles(lowest->second.loc,&locs[0]);
-               if(teleports != NULL && teleports->count(lowest->second.loc) != 
0) {
-                       
std::copy(teleports->begin(),teleports->end(),std::back_inserter(locs));
-               }
-
-               for(size_t j = 0; j != locs.size(); ++j) {
-
-                       //if we have found a solution
-                       if(locs[j] == dst) {
-                               LOG_PF << "found solution; calculating it...\n";
-                               paths::route rt;
-
-                               for(location loc = lowest->second.loc; 
loc.valid(); ) {
-                                       rt.steps.push_back(loc);
-                                       list_map::const_iterator itor = 
open_list.find(loc);
-                                       if(itor == open_list.end()) {
-                                               itor = closed_list.find(loc);
-                                               assert(itor != 
closed_list.end());
-                                       }
-
-                                       loc = itor->second.parent;
-                               }
-                               
-                               std::reverse(rt.steps.begin(),rt.steps.end());
-                               rt.steps.push_back(dst);
-                               rt.move_left = int(lowest->second.g + 
obj.cost(dst,lowest->second.g));
-
-                               assert(rt.steps.front() == src);
-
-                               LOG_PF << "exiting a* search (solved)\n";
-
-                               return rt;
-                       }
-
-                       list_map::iterator current_best = 
open_list.find(locs[j]);
-                       const bool in_open = current_best != open_list.end();
-                       if(!in_open) {
-                               current_best = closed_list.find(locs[j]);
-                       }
-
-                       if(current_best != closed_list.end() && 
current_best->second.g <= lowest->second.g+1.0) {
-                               continue;
-                       }
-
-                       const double new_cost = 
obj.cost(locs[j],lowest->second.g);
-
-                       const node nd(locs[j],dst,lowest->second.g+new_cost,
-                                     lowest->second.loc,teleports);
-
-                       if(current_best != closed_list.end()) {
-                               if(current_best->second.g <= nd.g) {
-                                       continue;
-                               } else if(in_open) {
-                                       typedef 
std::multimap<double,location>::iterator Itor;
-                                       std::pair<Itor,Itor> itors = 
open_list_ordered.equal_range(current_best->second.f);
-                                       while(itors.first != itors.second) {
-                                               if(itors.first->second == 
current_best->second.loc) {
-                                                       
open_list_ordered.erase(itors.first);
-                                                       break;
-                                               }
-                                               ++itors.first;
-                                       }
-
-                                       open_list.erase(current_best);
-                               } else {
-                                       closed_list.erase(current_best);
-                               }
-                       }
-
-                       if(nd.f < stop_at) {
-                               open_list.insert(list_type(nd.loc,nd));
-                               
open_list_ordered.insert(std::pair<double,location>(nd.f,nd.loc));
-                       } else {
-                               closed_list.insert(list_type(nd.loc,nd));
-                       }
-               }
-       }
-
-       LOG_PF << "aborted a* search\n";
-       paths::route val;
-       val.move_left = 100000;
-       return val;
-}
-
-#undef LOG_PF
+paths::route a_star_search(gamemap::location const &src, gamemap::location 
const &dst,
+                           double stop_at, cost_calculator const *obj,
+                           std::set<gamemap::location> const *teleports = 
NULL);
 
 #endif
Index: wesnoth/src/playturn.cpp
diff -u wesnoth/src/playturn.cpp:1.308 wesnoth/src/playturn.cpp:1.309
--- wesnoth/src/playturn.cpp:1.308      Sun Dec  5 19:54:26 2004
+++ wesnoth/src/playturn.cpp    Sun Dec  5 22:14:29 2004
@@ -1,4 +1,4 @@
-/* $Id: playturn.cpp,v 1.308 2004/12/05 19:54:26 silene Exp $ */
+/* $Id: playturn.cpp,v 1.309 2004/12/05 22:14:29 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -352,8 +352,7 @@
                                                
allowed_teleports.insert(un->first);
                                }
 
-                               current_route_ = 
a_star_search(selected_hex_,dest,
-                                                              
10000.0,calc,teleports);
+                               current_route_ = a_star_search(selected_hex_, 
dest, 10000.0, &calc, teleports);
 
                                current_route_.move_left = 
route_turns_to_complete(un->second,map_,current_route_);
 
@@ -835,8 +834,7 @@
 
                                }
 
-                               paths::route route = 
a_star_search(it->first,go_to,
-                                                              
10000.0,calc,teleports);
+                               paths::route route = a_star_search(it->first, 
go_to, 10000.0, &calc, teleports);
                                route.move_left = 
route_turns_to_complete(it->second,map_,route);
                                gui_.set_route(&route);
                        }
@@ -918,7 +916,7 @@
                        allowed_teleports.insert(ui->first);
        }
 
-       paths::route route = 
a_star_search(ui->first,target,10000.0,calc,teleports);
+       paths::route route = a_star_search(ui->first, target, 10000.0, &calc, 
teleports);
        if(route.steps.empty())
                return;
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]