MegaGlest/source/glest_game/ai/node_pool.cpp

135 lines
3.7 KiB
C++

// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2009 James McCulloch <silnarm at gmail>
//
// 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<Vec2i>* NodePool::getOpenNodes() {
list<Vec2i> *ret = new list<Vec2i>();
list<Vec2i>::iterator it = listedNodes.begin();
for ( ; it != listedNodes.end (); ++it) {
if (isOpen(*it)) ret->push_back(*it);
}
return ret;
}
list<Vec2i>* NodePool::getClosedNodes() {
list<Vec2i> *ret = new list<Vec2i>();
list<Vec2i>::iterator it = listedNodes.begin();
for ( ; it != listedNodes.end(); ++it) {
if (isClosed(*it)) ret->push_back(*it);
}
return ret;
}
#endif // _GAE_DEBUG_EDITION_
}}