move.cc

Go to the documentation of this file.
00001 /*                            Package   : libhex
00002  * move.cc                    Created   : 2008/02/19
00003  *                            Author    : Alex Tingle
00004  *
00005  *    Copyright (C) 2008, Alex Tingle.
00006  *
00007  *    This file is part of the libhex application.
00008  *
00009  *    libhex is free software; you can redistribute it and/or
00010  *    modify it under the terms of the GNU Lesser General Public
00011  *    License as published by the Free Software Foundation; either
00012  *    version 2.1 of the License, or (at your option) any later version.
00013  *
00014  *    libhex is distributed in the hope that it will be useful,
00015  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  *    Lesser General Public License for more details.
00018  *
00019  *    You should have received a copy of the GNU Lesser General Public
00020  *    License along with this library; if not, write to the Free Software
00021  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  */
00023 
00024 #include "hexmove.h"
00025 
00026 #include <cmath>
00027 
00028 
00029 namespace hex {
00030 namespace move {
00031 
00032 
00033 Topography::Topography()
00034   : _has_default(false), _default(0.0), _hexes(), _edges()
00035   {}
00036 
00037 
00038 Topography::Topography(Cost default_hex_cost)
00039   : _has_default(true), _default(default_hex_cost), _hexes(), _edges()
00040   {}
00041 
00042 
00043 std::set<hex::Hex*>
00044 Topography::accessible(void) const
00045 {
00046   using namespace std;
00047   set<hex::Hex*> result;
00048   for(map<hex::Hex*,Cost>::const_iterator i=_hexes.begin(); i!=_hexes.end();++i)
00049     result.insert(i->first);
00050   for(map<hex::Edge*,Cost>::const_iterator i=_edges.begin();i!=_edges.end();++i)
00051     result.insert(i->first->hex());
00052   return result;
00053 }
00054 
00055 
00056 void
00057 Topography::increase_hex_cost(hex::Hex* h, Cost c)
00058 {
00059   {
00060     std::map<hex::Hex*,Cost>::iterator pos = _hexes.find(h);
00061     if(pos==_hexes.end())
00062         _hexes[h] = _default + c;
00063     else
00064         pos->second += c;
00065   }
00066   for(int d=0; d<DIRECTIONS; ++d)
00067   {
00068     hex::Edge* e =h->edge(hex::A+d);
00069     std::map<hex::Edge*,Cost>::iterator pos = _edges.find(e);
00070     if(pos!=_edges.end())
00071         pos->second += c;
00072   }
00073 }
00074 
00075 
00076 void
00077 Topography::override_hex_cost(hex::Hex* h, Cost c)
00078 {
00079   _hexes[h] = c;
00080   for(int d=0; d<DIRECTIONS; ++d)
00081   {
00082     hex::Edge* e =h->edge(hex::A+d);
00083     _edges.erase(e);
00084   }
00085 }
00086       
00087 void Topography::increase_edge_cost(hex::Edge* e, Cost c)
00088 {
00089   if(!e)
00090     return;
00091   std::map<hex::Edge*,Cost>::iterator epos = _edges.find(e);
00092   if(epos==_edges.end())
00093   {
00094     std::map<hex::Hex*,Cost>::iterator hpos = _hexes.find( e->hex() );
00095     if(hpos!=_hexes.end())
00096       _edges[e] = hpos->second + c;
00097     else if(_has_default)
00098       _edges[e] = _default + c;
00099   }
00100   else
00101   {
00102     epos->second += c;
00103   }
00104 }
00105 
00106 
00107 void
00108 Topography::override_edge_cost(hex::Edge* e, Cost c)
00109 {
00110   if(e)
00111     _edges[e] = c;
00112 }
00113 
00114 
00115 void
00116 Topography::increase_cost(const hex::Area& a, Cost c)
00117 {
00118   const std::set<hex::Hex*>& hexes = a.hexes();
00119   for(std::set<hex::Hex*>::const_iterator i=hexes.begin(); i!=hexes.end(); ++i)
00120     increase_hex_cost(*i,c);
00121 }
00122 
00123 
00124 void
00125 Topography::override_cost(const hex::Area& a, Cost c)
00126 {
00127   const std::set<hex::Hex*>& hexes = a.hexes();
00128   for(std::set<hex::Hex*>::const_iterator i=hexes.begin(); i!=hexes.end(); ++i)
00129     override_hex_cost(*i,c);
00130 }
00131 
00132 
00133 void
00134 Topography::increase_cost(const hex::Boundary& b, Cost c)
00135 {
00136   const std::list<hex::Edge*>& edges = b.edges();
00137   for(std::list<hex::Edge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i)
00138     increase_edge_cost(*i,c);
00139 }
00140 
00141 
00142 void
00143 Topography::override_cost(const hex::Boundary& b, Cost c)
00144 {
00145   const std::list<hex::Edge*>& edges = b.edges();
00146   for(std::list<hex::Edge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i)
00147     override_edge_cost(*i,c);
00148 }
00149 
00150 
00151 hex::Path
00152 Topography::best_path(hex::Hex* start, hex::Hex* goal) const throw(no_solution)
00153 {
00154   std::set<hex::Hex*> visited;
00155   std::multiset<_Route> queue;
00156   queue.insert( _Route::factory(start,goal) );
00157   while(!queue.empty())
00158   {
00159     _Route curr_route = *queue.begin();
00160     queue.erase( queue.begin() );
00161     hex::Hex* curr_hex = curr_route.path.back();
00162     if(visited.count(curr_hex))
00163         continue;
00164     if(curr_hex==goal)
00165         return hex::Path(curr_route.path);
00166     visited.insert(curr_hex);
00167     for(int dir=0; dir<DIRECTIONS; ++dir)
00168     {
00169       Topography::Step s = step(curr_hex,hex::A+dir);
00170       if(s.to_hex && 0==visited.count(s.to_hex))
00171           queue.insert( curr_route.step(s.to_hex,s.cost,goal) );
00172     }
00173   }
00174   throw no_solution("best_path");
00175 }
00176 
00177 
00178 hex::Area
00179 Topography::horizon(hex::Hex* start, Cost budget) const throw(no_solution)
00180 {
00181   std::set<hex::Hex*> visited;
00182   std::multiset<_Route> queue;
00183   queue.insert( _Route::factory(start) );
00184   while(!queue.empty())
00185   {
00186     _Route curr_route = *queue.begin();
00187     queue.erase( queue.begin() );
00188     hex::Hex* curr_hex = curr_route.path.back();
00189     if(visited.count(curr_hex))
00190         continue;
00191     if(curr_route.cost > budget)
00192         continue;
00193     visited.insert(curr_hex);
00194     for(int dir=0; dir<DIRECTIONS; ++dir)
00195     {
00196       Topography::Step s = step(curr_hex,hex::A+dir);
00197       if(s.to_hex && 0==visited.count(s.to_hex))
00198           queue.insert( curr_route.step(s.to_hex,s.cost) );
00199     }
00200   }
00201   return visited;
00202 }
00203 
00204 
00205 Topography::Step
00206 Topography::step(hex::Hex* from_hex, Direction direction) const
00207 {
00208   Step result = {NULL,_default};
00209   // Find destination
00210   result.to_hex = from_hex->go(direction);
00211   if(!result.to_hex)
00212     return result;
00213   // If there's an edge cost, then use that.
00214   hex::Edge* to_edge = result.to_hex->edge(direction+3);
00215   std::map<hex::Edge*,Cost>::const_iterator epos = _edges.find(to_edge);
00216   if(epos!=_edges.end())
00217   {
00218     result.cost = epos->second;
00219     return result;
00220   }
00221   // Otherwise use cost of to_hex
00222   std::map<hex::Hex*,Cost>::const_iterator hpos = _hexes.find( result.to_hex );
00223   if(hpos!=_hexes.end())
00224       result.cost = hpos->second;
00225   else if(!_has_default)
00226       result.to_hex = NULL;
00227   return result;
00228 }
00229 
00230 
00231 //
00232 // ROUTE
00233 
00234 _Route
00235 _Route::factory(hex::Hex* start, hex::Hex* goal)
00236 {
00237   _Route result;
00238   result.path.push_back(start);
00239   result.cost  = 0; // g()
00240   result._value = result.distance(goal); // f()
00241   return result;
00242 }
00243 
00244 
00245 _Route
00246 _Route::step(hex::Hex* next, Cost cost, hex::Hex* goal) const
00247 {
00248   _Route result;
00249   result.path  = path;
00250   result.path.push_back(next);
00251   result.cost  = this->cost + cost; // g()
00252   result._value = result.cost + result.distance(goal); // f()
00253   return result;
00254 }
00255 
00256    
00257 hex::Distance
00258 _Route::distance(hex::Hex* goal) const
00259 {
00260   if(goal)
00261   {
00262     hex::Point vector = goal->centre() - path.back()->centre();
00263     return sqrt( vector.x * vector.x  +  vector.y * vector.y );
00264   }
00265   return 0;
00266 }
00267 
00268 
00269 } // end namespace svg
00270 } // end namespace hex

Generated on Thu Feb 21 00:00:54 2008 for libhex by  doxygen 1.5.1