// ==============================================================
// 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
// ==============================================================
#ifndef _GLEST_GAME_ASTAR_NODE_MAP_H_
#define _GLEST_GAME_ASTAR_NODE_MAP_H_
#include "game_constants.h"
#include "vec.h"
#include "world.h"
namespace Glest { namespace Game {
using Shared::Graphics::Vec2i;
using Shared::Platform::uint16;
using Shared::Platform::uint32;
#define MAX_MAP_COORD_BITS 16
#define MAX_MAP_COORD ((1<Node status for this search,
* - mark < NodeMap::searchCounter => unvisited
* - mark == NodeMap::searchCounter => open
* - mark == NodeMap::searchCounter + 1 => closed
*/
uint32 mark;
/** best route to here is from, valid only if this node is closed */
PackedPos prevNode;
/** 'next' node in open list, valid only if this node is open */
PackedPos nextOpen;
/** heuristic from this cell, valid only if node visited */
float heuristic;
/** cost to this cell, valid only if node visited */
float distToHere;
/** Construct NodeMapCell */
NodeMapCell() { memset(this, 0, sizeof(*this)); }
/** the estimate function, costToHere + heuristic */
float estimate() { return heuristic + distToHere; }
};
#pragma pack(pop)
/** Wrapper for the NodeMapCell array */
class NodeMapCellArray {
private:
NodeMapCell *array;
int stride;
public:
NodeMapCellArray() { array = NULL; }
~NodeMapCellArray() { delete [] array; }
void init(int w, int h) { delete [] array; array = new NodeMapCell[w * h]; stride = w; }
/** index by Vec2i */
NodeMapCell& operator[] (const Vec2i &pos) { return array[pos.y * stride + pos.x]; }
/** index by PackedPos */
NodeMapCell& operator[] (const PackedPos pos) { return array[pos.y * stride + pos.x]; }
};
/** A NodeStorage (template interface) compliant NodeMap. Keeps a store of nodes the size of
* the map, and embeds the open and cosed list within. Uses some memory, but goes fast.
*/
class NodeMap {
public:
NodeMap(Map *map);
// NodeStorage template interface
//
void reset();
/** set a maximum number of nodes to expand */
void setMaxNodes(int limit) { nodeLimit = limit > 0 ? limit : -1; }
/** is the node at pos open */
bool isOpen(const Vec2i &pos) { return nodeMap[pos].mark == searchCounter; }
/** is the node at pos closed */
bool isClosed(const Vec2i &pos) { return nodeMap[pos].mark == searchCounter + 1; }
bool setOpen(const Vec2i &pos, const Vec2i &prev, float h, float d);
void updateOpen(const Vec2i &pos, const Vec2i &prev, const float cost);
Vec2i getBestCandidate();
/** get the best heuristic node seen this search */
Vec2i getBestSeen() { return bestH.valid() ? Vec2i(bestH) : Vec2i(-1); }
/** get the heuristic of the node at pos [known to be visited] */
float getHeuristicAt(const Vec2i &pos) { return nodeMap[pos].heuristic; }
/** get the cost to the node at pos [known to be visited] */
float getCostTo(const Vec2i &pos) { return nodeMap[pos].distToHere; }
/** get the estimate for the node at pos [known to be visited] */
float getEstimateFor(const Vec2i &pos) { return nodeMap[pos].estimate(); }
/** get the best path to the node at pos [known to be visited] */
Vec2i getBestTo(const Vec2i &pos) {
return nodeMap[pos].prevNode.valid() ? Vec2i(nodeMap[pos].prevNode) : Vec2i(-1);
}
private:
/** The array of nodes */
NodeMapCellArray nodeMap;
Map *cellMap;
/** The stride of the array */
int stride;
/** The current node expansion limit */
int nodeLimit;
/** A counter, with NodeMapCell::mark determines validity of nodes in current search */
uint32 searchCounter,
/** Number of nodes expanded this/last search */
nodeCount;
/** An invalid PackedPos */
PackedPos invalidPos;
/** The lowest heuristic node seen this/last search */
PackedPos bestH;
/** The top of the open list is at */
Vec2i openTop;
/** Debug */
bool assertValidPath(list &path);
/** Debug */
bool assertOpen();
/** Debug */
void logOpen();
#ifdef _GAE_DEBUG_EDITION_
public:
list* getOpenNodes ();
list* getClosedNodes ();
list listedNodes;
#endif
};
}}
#endif