// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2009 James McCulloch // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== // // File: node_pool.cpp // #include "node_pool.h" #include "world.h" #include "map.h" namespace Glest { namespace Game { // ===================================================== // class NodePool // ===================================================== NodePool::NodePool(int w, int h) : counter(0) , leastH(NULL) , numNodes(0) , tmpMaxNodes(size) , markerArray(w, h) { stock = new AStarNode[size]; } NodePool::~NodePool() { delete [] stock; } /** reset the node pool for a new search (resets tmpMaxNodes too) */ void NodePool::reset() { numNodes = 0; counter = 0; tmpMaxNodes = size; leastH = NULL; markerArray.newSearch(); openHeap.clear(); //IF_DEBUG_EDITION( listedNodes.clear(); ) } /** set a maximum number of nodes to expand */ void NodePool::setMaxNodes(const int max) { assert(max >= 32 && max <= size); // reasonable number ? assert(!numNodes); // can't do this after we've started using it. tmpMaxNodes = max; } /** marks an unvisited position as open * @param pos the position to open * @param prev the best known path to pos is from * @param h the heuristic for pos * @param d the costSoFar for pos * @return true if added, false if node limit reached */ bool NodePool::setOpen(const Vec2i &pos, const Vec2i &prev, float h, float d) { assert(!isOpen(pos)); AStarNode *node = newNode(); if (!node) { // NodePool exhausted return false; } //IF_DEBUG_EDITION( listedNodes.push_back(pos); ) node->posOff = pos; if (prev.x >= 0) { node->posOff.ox = prev.x - pos.x; node->posOff.oy = prev.y - pos.y; } else { node->posOff.ox = 0; node->posOff.oy = 0; } node->distToHere = d; node->heuristic = h; addOpenNode(node); if (!numNodes || h < leastH->heuristic) { leastH = node; } numNodes++; return true; } /** add a new node to the open list @param node pointer to the node to add */ void NodePool::addOpenNode(AStarNode *node) { assert(!isOpen(node->pos())); markerArray.setOpen(node->pos()); markerArray.set(node->pos(), node); openHeap.insert(node); } /** conditionally update a node on the open list. Tests if a path through a new nieghbour * is better than the existing known best path to pos, updates if so. * @param pos the open postion to test * @param prev the new path from * @param cost the cost to here from prev */ void NodePool::updateOpen(const Vec2i &pos, const Vec2i &prev, const float cost) { assert(isClosed(prev)); assert(isOpen(pos)); AStarNode *posNode, *prevNode; posNode = markerArray.get(pos); prevNode = markerArray.get(prev); if (prevNode->distToHere + cost < posNode->distToHere) { posNode->posOff.ox = prev.x - pos.x; posNode->posOff.oy = prev.y - pos.y; posNode->distToHere = prevNode->distToHere + cost; openHeap.promote(posNode); } } #if _GAE_DEBUG_EDITION_ list* NodePool::getOpenNodes() { list *ret = new list(); list::iterator it = listedNodes.begin(); for ( ; it != listedNodes.end (); ++it) { if (isOpen(*it)) ret->push_back(*it); } return ret; } list* NodePool::getClosedNodes() { list *ret = new list(); list::iterator it = listedNodes.begin(); for ( ; it != listedNodes.end(); ++it) { if (isClosed(*it)) ret->push_back(*it); } return ret; } #endif // _GAE_DEBUG_EDITION_ }}