astarnode.cpp

Go to the documentation of this file.
00001 /* $Id: astarnode.cpp 23842 2008-02-16 08:47:16Z mordante $ */
00002 /*
00003 Copyright (C) 2003 by David White <dave@whitevine.net>
00004 Copyright (C) 2005 - 2008 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
00005 Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License version 2
00009 or at your option any later version.
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY.
00012 
00013 See the COPYING file for more details.
00014 */
00015 
00016 #include "global.hpp"
00017 #include "astarnode.hpp"
00018 
00019 #include <cassert>
00020 
00021 void a_star_node::initNode(gamemap::location const &pos, gamemap::location const &dst,
00022                            double cost, a_star_node *parent, std::set<gamemap::location> const *teleports)
00023 {
00024     isInCloseList = false;
00025     loc = pos;
00026     nodeParent = parent;
00027     g = cost;
00028     h = heuristic(pos, dst);
00029     //if there are teleport locations, correct the heuristic to take them into account
00030     if (teleports != NULL) {
00031         double srch = h, dsth = h;
00032         std::set<gamemap::location>::const_iterator i;
00033         for(i = teleports->begin(); i != teleports->end(); ++i) {
00034             const double new_srch = heuristic(pos, *i);
00035             const double new_dsth = heuristic(*i, dst);
00036             if(new_srch < srch) {
00037                 srch = new_srch;
00038             }
00039             if(new_dsth < dsth) {
00040                 dsth = new_dsth;
00041             }
00042         }
00043         if(srch + dsth + 1.0 < h) {
00044             h = srch + dsth + 1.0;
00045         }
00046     }
00047 }
00048 
00049 class a_star_world::poss_a_star_node
00050 {
00051 private:
00052     typedef std::vector<a_star_node*> vect_page_a_star_node;
00053     vect_page_a_star_node vectPageAStarNode_;
00054     size_t nbElemByPage_;
00055     size_t capacity_;
00056     size_t curIndex_;
00057     void addPage();
00058 
00059 public:
00060     poss_a_star_node();
00061     ~poss_a_star_node();
00062     a_star_node *getAStarNode();
00063     void clear();
00064 };
00065 
00066 void a_star_world::poss_a_star_node::addPage()
00067 {
00068     vectPageAStarNode_.push_back(new a_star_node[nbElemByPage_]);
00069     capacity_ += nbElemByPage_;
00070 }
00071 
00072 a_star_world::poss_a_star_node::poss_a_star_node()
00073     : capacity_(0), curIndex_(0)
00074 {
00075     nbElemByPage_ = size_t((4096 - 24) / sizeof(a_star_node));
00076     assert(nbElemByPage_ > 0);
00077     addPage();
00078 }
00079 
00080 a_star_world::poss_a_star_node::~poss_a_star_node()
00081 {
00082     for(vect_page_a_star_node::iterator iter = vectPageAStarNode_.begin(),
00083                                         iend = vectPageAStarNode_.end();
00084         iter != iend; ++iter)
00085         delete[] *iter;
00086 }
00087 
00088 a_star_node *a_star_world::poss_a_star_node::getAStarNode()
00089 {
00090     //----------------- PRE_CONDITIONS ------------------
00091     assert(capacity_ > 0);
00092     assert(curIndex_ <= capacity_);
00093     //---------------------------------------------------
00094     if (curIndex_ == capacity_)
00095         addPage();
00096     size_t i = curIndex_++;
00097     return &vectPageAStarNode_[i / nbElemByPage_][i % nbElemByPage_];
00098 }
00099 
00100 void a_star_world::poss_a_star_node::clear()
00101 {
00102     if (capacity_ > nbElemByPage_) {
00103         for(vect_page_a_star_node::iterator iter = vectPageAStarNode_.begin() + 1,
00104                                             iend = vectPageAStarNode_.end();
00105             iter != iend; ++iter)
00106             delete[] *iter;
00107         vectPageAStarNode_.resize(1);
00108         capacity_ = nbElemByPage_;
00109     }
00110     curIndex_ = 0;
00111     //----------------- POST_CONDITIONS -----------------
00112     assert(capacity_ == nbElemByPage_);
00113     assert(vectPageAStarNode_.size() == 1);
00114     //---------------------------------------------------
00115 }
00116 
00117 a_star_world::a_star_world()
00118     : pool_(new poss_a_star_node), width_(0), nbNode_(0)
00119 {
00120 }
00121 
00122 a_star_world::~a_star_world()
00123 {
00124     delete pool_;
00125 }
00126 
00127 void a_star_world::resize_IFN(size_t parWidth, size_t parHeight)
00128 {
00129     //----------------- PRE_CONDITIONS ------------------
00130     assert(nbNode_ == 0);
00131     //---------------------------------------------------
00132     width_ = parWidth;
00133     size_t sz = parWidth * parHeight;
00134     if (vectAStarNode_.size() == sz)
00135         return;
00136     vectAStarNode_.reserve(sz);
00137     vectAStarNode_.resize(sz);
00138 }
00139 
00140 void a_star_world::clear(void)
00141 {
00142     a_star_node *locNode = NULL;
00143     std::fill(vectAStarNode_.begin(), vectAStarNode_.end(), locNode);
00144     nbNode_ = 0;
00145     pool_->clear();
00146 }
00147 
00148 a_star_node *a_star_world::getNodeFromLocation(gamemap::location const &loc, bool &isCreated)
00149 {
00150     //----------------- PRE_CONDITIONS ------------------
00151     assert(loc.valid());
00152     assert(loc.x + loc.y * width_ < vectAStarNode_.size());
00153     //---------------------------------------------------
00154 
00155     a_star_node *&node = vectAStarNode_[loc.x + loc.y * width_];
00156     if ((isCreated = (node == NULL))) {
00157         node = pool_->getAStarNode();
00158         ++nbNode_;
00159     }
00160     return node;
00161 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs