
// should only be included by rail_move.hpp

//--------------------------------------------------------------------


namespace MW4AI
{


	inline gridpoint::gridpoint (int p1,int p2)
	{
		Verify (p1>=(MinX/10.0f));
		Verify (p2>=(MinZ/10.0f));
		if (p1 < MinX/10.0f)
			p1 = (int) (MinX/10.0f);
		if (p2 < MinZ/10.0f)
			p2 = (int) (MinZ/10.0f);
		if (p1 >= (MaxX/10.0f))
			p1 = (int) (MaxX/10.0f)-1;
		if (p2 >= (MaxZ/10.0f))
			p2 = (int) (MaxZ/10.0f)-1;
		x = p1;
		y = p2;
	}
	inline gridpoint::gridpoint (float p1,float p2)
	{
		Verify (p1>=(MinX/10.0f));
		Verify (p2>=(MinZ/10.0f));
		if (p1 < MinX/10.0f)
			p1 = MinX/10.0f;
		if (p2 < MinZ/10.0f)
			p2 = MinZ/10.0f;
		if (p1 >= (MaxX/10.0f))
			p1 = (MaxX/10.0f)-1;
		if (p2 >= (MaxZ/10.0f))
			p2 = (MaxZ/10.0f)-1;
		x = (int) p1;
		y = (int) p2;
	}

	inline CRailLink::CRailLink (void)
	{
		m_Loc[0] = m_Loc[1] = NULL;
		memset (m_Weight,0,sizeof (m_Weight));
		memset (m_CalcedWeight,0,sizeof (m_CalcedWeight));
		m_UsageFlags[0] = LEGFLAG;
		m_UsageFlags[1] = LEGFLAG;
		m_Bridge = -1;
	}
	inline CRailLink::CRailLink (CRailNode *loc1,CRailNode *loc2,float weight[NUM_MOVE_TYPES][2],bool jump[2],bool track[2],bool fly[2],bool wheel[2],bool leg[2],bool hover[2],bool heli[2])
	{
		m_UsageFlags[0] = 0;
		m_UsageFlags[1] = 0;
		m_Loc[0] = loc1;
		m_Loc[1] = loc2;
		memcpy (m_Weight,weight,sizeof (m_Weight));
		memcpy (m_CalcedWeight,weight,sizeof (m_CalcedWeight));
		m_UsageFlags[0] |= jump[0] ? JUMPFLAG : 0;
		m_UsageFlags[0] |= track[0] ? TRACKFLAG : 0;
		m_UsageFlags[0] |= fly[0] ? FLYFLAG : 0;
		m_UsageFlags[0] |= wheel[0] ? WHEELFLAG : 0;
		m_UsageFlags[0] |= leg[0] ? LEGFLAG : 0;
		m_UsageFlags[0] |= hover[0] ? HOVERFLAG : 0;
		m_UsageFlags[0] |= heli[0] ? HELIFLAG : 0;

		m_UsageFlags[1] |= jump[1] ? JUMPFLAG : 0;
		m_UsageFlags[1] |= track[1] ? TRACKFLAG : 0;
		m_UsageFlags[1] |= fly[1] ? FLYFLAG : 0;
		m_UsageFlags[1] |= wheel[1] ? WHEELFLAG : 0;
		m_UsageFlags[1] |= leg[1] ? LEGFLAG : 0;
		m_UsageFlags[1] |= hover[1] ? HOVERFLAG : 0;
		m_UsageFlags[1] |= heli[1] ? HELIFLAG : 0;
		m_Bridge = -1;
	}
	inline CRailLink::CRailLink (CRailNode *loc1,CRailNode *loc2,float weight[NUM_MOVE_TYPES][2],int moveflags[2])
	{
		for (int k=0;k<2;k++)
		{
			if (moveflags[k] == 0xffffffff)
			{
				int i;
				m_UsageFlags[k] = 0;
				for (i=0;i<NUM_MOVE_TYPES;i++)
				{
					if (weight[i][k] != -1.0f)
						m_UsageFlags[k] |= 1<<i;
				}
			}
			else
				m_UsageFlags[k]	= moveflags[k];
		}
		m_Loc[0] = loc1;
		m_Loc[1] = loc2;
		memcpy (m_Weight,weight,sizeof (m_Weight));
		memcpy (m_CalcedWeight,weight,sizeof (m_CalcedWeight));
		m_Bridge = -1;
	}

	inline CRailLink::~CRailLink()
	{
	}

	inline float CRailLink::Weight (int type,CRailNode *src) const
	{
		Verify (type>=0);
		Verify (type<NUM_MOVE_TYPES);
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
			return m_Weight[type][0];
		else
			return m_Weight[type][1];
	}
	inline float CRailLink::LowestWeight (int usage,int &type,CRailNode *src) const
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		int index;

		if (m_Loc[0] == src)
			index = 0;
		else
			index	= 1;
		int i;
		int min=-1;
		for (i=0;i<NUM_MOVE_TYPES;i++)
		{
			if (i == JUMPINDEX)// && (m_Weight[i][index] > 125.0f))
				continue;
			if (usage & (1<<i))
			{
				if (min ==-1)
					min = i;
				else if ((m_Weight[i][index] < m_Weight[min][index]) && (m_Weight[i][index] != -1.0f))
					min = i;
			}
		}
		type = (1<<min);
		if (min == -1)
			return -1.0f;
		return m_Weight[min][index];
	}

	inline void CRailLink::Weight (float amount,int which,CRailNode *src,bool calc)
	{
		Verify (which>=0);
		Verify (which<NUM_MOVE_TYPES);
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		int index;

		if (m_Loc[0] == src)
			index = 0;
		else
			index	= 1;

		m_Weight[which][index] = amount;
		if (calc)
			m_CalcedWeight[which][index] = amount;
	}
	inline void CRailLink::Jump (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~JUMPFLAG;
			m_UsageFlags[0] |= p1 ? JUMPFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~JUMPFLAG;
			m_UsageFlags[1] |= p1 ? JUMPFLAG : 0;
		}
	}
	inline void CRailLink::Tracked (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~TRACKFLAG;
			m_UsageFlags[0] |= p1 ? TRACKFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~TRACKFLAG;
			m_UsageFlags[1] |= p1 ? TRACKFLAG : 0;
		}
	}
	inline void CRailLink::Flyer (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~FLYFLAG;
			m_UsageFlags[0] |= p1 ? FLYFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~FLYFLAG;
			m_UsageFlags[1] |= p1 ? FLYFLAG : 0;
		}
	}
	inline void CRailLink::Wheeled (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~WHEELFLAG;
			m_UsageFlags[0] |= p1 ? WHEELFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~WHEELFLAG;
			m_UsageFlags[1] |= p1 ? WHEELFLAG : 0;
		}
	}
	inline void CRailLink::Legged (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~LEGFLAG;
			m_UsageFlags[0] |= p1 ? LEGFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~LEGFLAG;
			m_UsageFlags[1] |= p1 ? LEGFLAG : 0;
		}
	}
	inline void CRailLink::Hover (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~HOVERFLAG;
			m_UsageFlags[0] |= p1 ? HOVERFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~HOVERFLAG;
			m_UsageFlags[1] |= p1 ? HOVERFLAG : 0;
		}
	}
	inline void CRailLink::Heli (bool p1,CRailNode *src)
	{
		Verify ((src == m_Loc[0]) || (src == m_Loc[1]));
		if (m_Loc[0] == src)
		{
			m_UsageFlags[0] &= ~HELIFLAG;
			m_UsageFlags[0] |= p1 ? HELIFLAG : 0;
		}
		else
		{
			m_UsageFlags[1] &= ~HELIFLAG;
			m_UsageFlags[1] |= p1 ? HELIFLAG : 0;
		}
	}

	inline const CRailNode *CRailLink::Location (unsigned int id) const
	{
		Verify ((id>=0) && (id<=1));
		Verify (m_Loc[id]);
		return m_Loc[id];
	}
	inline unsigned int CRailLink::LocID (unsigned int id) const
	{
		Verify ((id>=0) && (id<=1));
		return m_LocID[id];
	}
	inline CRailNode *CRailLink::OtherLocation (const CRailNode *temp)
	{
		Verify ((temp == m_Loc[0]) || (temp == m_Loc[1]));
		if (m_Loc[0] == temp)
			return m_Loc[1];
		else
			return m_Loc[0];
	}
	inline CRailNode *CRailLink::Location (int id)
	{
		Verify ((id>=0) && (id<=1));
		return m_Loc[id];
	}

	inline CRailNode::RailSubNode::RailSubNode (Stuff::Scalar p1,Stuff::Scalar p2,Stuff::Scalar p3)
	{
		location.x = p1;
		location.y = p2;
		location.z = p3;
	}
	inline CRailNode::RailSubNode& CRailNode::RailSubNode::operator= (const RailSubNode& p1)
	{
		location = p1.location;
		return *this;
	}


	inline void CRailNode::Location (const Stuff::Point3D& newloc)
	{
		m_Location = newloc;
		m_Dirty = true;

	}

	inline CRailLink *CRailNode::LinkTo (CRailNode *dest)
	{
		stlport::vector<CRailLink *>::iterator iter;
		
		for (iter = m_Links.begin ();iter != m_Links.end ();iter++)
		{
			if ((*iter)->OtherLocation (this) == dest)
			{
				return *iter;
			}
		}
		return NULL;
	}

	inline CRailLink *CRailNode::Link (unsigned int id) const
	{
		Verify (id>=0);
		Verify (id<m_Links.size ());
		return m_Links[id];
	}
	inline void CRailNode::ClearLinks (void)
	{
		m_Links.clear ();
		m_SubNodes.clear ();
	}
	inline CRailNode::RailSubNode CRailNode::SubNode (unsigned int id)
	{
		Verify (id>=0);
		Verify (id<m_SubNodes.size ());
		return m_SubNodes[id];
	}
	inline CRailNode::RailSubNode CRailNode::SubNode (CRailLink *link)
	{
		int i,size;

		size = m_Links.size ();
		for (i=0;i<size;i++)
			if (m_Links[i] == link)
				return SubNode (i);
		gosASSERT (false);
		return CRailNode::RailSubNode (Stuff::Point3D (-1,-1,-1));
	}
	inline unsigned int CRailNode::LinkID (unsigned int index)
	{
		Verify (index >=0);
		Verify (index < m_Links.size ());
		return m_Links[index]->ID ();
	}
	inline float CRailNode::EditorDistance (CRailNode *dest) const
	{
		Verify (dest);
		Verify (dest->ID () < m_EditorDistance.size ());
		Verify (m_DistanceValid);
		return m_EditorDistance[dest->ID ()];
	}
	inline float CRailNode::EditorDistance (unsigned int id) const
	{
		Verify (id < m_EditorDistance.size ());
		Verify (m_DistanceValid);
		return m_EditorDistance[id];
	}

	inline bool CRailNode::PathWeight (float newvalue,float estimate,int type)					// true if changed
	{
		if (((m_PathWeight+m_PathEstimate) > (newvalue+estimate)) || (m_PathWeight == 0.0))
		{
			m_PathWeight = newvalue;
			m_PathType = type;
			m_PathEstimate = estimate;
			return true;
		}
		return false;
	}
	inline void CRailNode::ClearPathWeight (float newvalue,float newestimate,int type)
	{
		m_PathWeight = newvalue;
		m_PathEstimate = newestimate;
		m_PathType = type;
	}

	inline void CMoveGrid::Destroy (void)
	{
#if 0
		int i,size;
		size = m_AllocHeight;
		for (i=0;i<size;i++)
		{
			delete[] m_Data[i];
		}
#endif
		delete[] m_Data;
		m_Data = NULL;
		DeleteMacroData ();
	}
	inline void CMoveGrid::Construct (int width,int height)
	{
		if (m_Data)
		{
			Destroy ();
		}

		m_Width = width;
		m_Height = height;
		width /= BLOCK_GRID_RES;
		height /= BLOCK_GRID_RES;
		gos_PushCurrentHeap(g_RailHeap);
		m_Data = new unsigned short[width*height];
		m_AllocHeight = height;
		m_AllocWidth = width;
		for (int i=0;i<(width*height);i++)
		{
			m_Data[i] = BLOCKED_FLAGS;
		}
#if 0
		m_Data = new unsigned short *[height];
		for (int i=0;i<height;i++)
		{
			m_Data[i] = new unsigned short[width];
		}
#endif
		gos_PopCurrentHeap ();
	}

inline int CGridPath::AdjustCost (int cx,int cy)
{
	Verify (m_Graph);
	return 0;
//	return m_Graph->MacroPassableLocal (cx>>3,cy>>3) * 5;
}

	inline void CMoveGrid::Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass)		// in meters
	{
//		x -= MinX;
//		z -= MinZ;
		x += 2560;
		z += 2560;
		Verify (x>=0);
		Verify (z>=0);
		Verify (x<m_Width);
		Verify (z<m_Height);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if (x>=m_Width)
			return ;
		if (z>=m_Height)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif

		int ix,iz;

		iz = (int) (z / BLOCK_GRID_RES);
		ix = (int) (x / BLOCK_GRID_RES);
		Verify (ix>=0);
		Verify (ix<m_AllocWidth);
		Verify (iz>=0);
		Verify (iz<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		m_Data[(iz<<9)+ix] |= canpass;
	}
	
	inline void CMoveGrid::PassableOverride (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass)		// in meters
	{
//		x -= MinX;
//		z -= MinZ;
		x += 2560;
		z += 2560;
		Verify (x>=0);
		Verify (z>=0);
		Verify (x<m_Width);
		Verify (z<m_Height);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if (x>=m_Width)
			return ;
		if (z>=m_Height)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif

		int ix,iz;

		iz = (int) (z / BLOCK_GRID_RES);
		ix = (int) (x / BLOCK_GRID_RES);
		Verify (ix>=0);
		Verify (ix<m_AllocWidth);
		Verify (iz>=0);
		Verify (iz<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		m_Data[(iz<<9)+ix] = 0;
		m_Data[(iz<<9)+ix] |= canpass;
	}

	inline unsigned short CMoveGrid::Passable (Stuff::Scalar x,Stuff::Scalar z) const						// in meters
	{
		Verify ((m_Width!=0) && (m_Height != 0));
		x += 2560;
		z += 2560;
//		x -= MinX;
//		z -= MinZ;
		Verify ((int) (x)>=0);
		Verify ((int) (z)>=0);
		Verify ((int) (x)<m_Width);
		Verify ((int) (z)<m_Height);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if ((int) (x)>=m_Width)
			return -1;
		if ((int) (z)>=m_Height)
			return -1;
		if ((int) (x)<0)
			return -1;
		if ((int) (z)<0)
			return -1;
#endif

		int ix,iz;

		iz = (int) ( (z / BLOCK_GRID_RES));
		ix = (int) ( (x / BLOCK_GRID_RES));
		Verify (ix>=0);
		Verify (ix<m_AllocWidth);
		Verify (iz>=0);
		Verify (iz<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		return(unsigned short) (m_Data[(iz<<9)+ix]);
	}

	inline unsigned short CMoveGrid::PassableLocal (int x,int z) const						// in local
	{
		Verify ((m_AllocWidth!=0) && (m_AllocHeight != 0));

		x += 256;
		z += 256;
//		x -= (int) (MinX/BLOCK_GRID_RES);
//		z -= (int) (MinZ/BLOCK_GRID_RES);

//	These cases are all handled below, so we shouldn't have to warn about them.
    Verify (x>=0);
		Verify (x<m_AllocWidth);
		Verify (z>=0);
		Verify (z<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if ((int) (x)>=m_AllocWidth)
			return -1;
		if ((int) (z)>=m_AllocHeight)
			return -1;
		if ((int) (x)<0)
			return -1;
		if ((int) (z)<0)
			return -1;
#endif
		Verify (m_AllocWidth == 512);
		return(unsigned short) (m_Data[(z<<9)+x]);
	}
	inline void CMoveGrid::PassableLocal (int x,int z,unsigned short canpass)						// in local
	{
		Verify ((m_AllocWidth!=0) && (m_AllocHeight != 0));

		x += 256;
		z += 256;
//		x -= (int) (MinX/BLOCK_GRID_RES);
//		z -= (int) (MinZ/BLOCK_GRID_RES);
		Verify (x>=0);
		Verify (x<m_AllocWidth);
		Verify (z>=0);
		Verify (z<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if (x>=m_AllocWidth)
			return ;
		if (z>=m_AllocHeight)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif

		Verify (m_AllocWidth == 512);
		m_Data[(z<<9)+x] |= canpass;
	}
	
	inline void CMoveGrid::PassableLocalOverride (int x,int z,unsigned short canpass)						// in local
	{
		Verify ((m_AllocWidth!=0) && (m_AllocHeight != 0));

		x += 256;
		z += 256;
//		x -= (int) (MinX/BLOCK_GRID_RES);
//		z -= (int) (MinZ/BLOCK_GRID_RES);
		Verify (x>=0);
		Verify (x<m_AllocWidth);
		Verify (z>=0);
		Verify (z<m_AllocHeight);
		Verify (m_AllocWidth == 512);
		Verify (m_AllocHeight == 512);
#if 0
		if (x>=m_AllocWidth)
			return ;
		if (z>=m_AllocHeight)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif

		Verify (m_AllocWidth == 512);
		m_Data[(z<<9)+x] = 0;
		m_Data[(z<<9)+x] |= canpass;
	}
	
	inline unsigned char CMoveGrid::MacroPassable (Stuff::Scalar x,Stuff::Scalar z) const
	{
		Verify ((m_Width!=0) && (m_Height != 0));
//		x -= MinX;
//		z -= MinZ;
		x += 2560;
		z += 2560;
		Verify ((int) (x)>=0);
		Verify ((int) (z)>=0);
		Verify ((int) (x)<m_Width);
		Verify ((int) (z)<m_Height);
#if 0
		if ((int) (x)>=m_Width)
			return 255;
		if ((int) (z)>=m_Height)
			return 255;
		if ((int) (x)<0)
			return 255;
		if ((int) (z)<0)
			return 255;
#endif

		int ix,iz;

		iz = (int) ( (z / MACROBLOCK_GRID_RES));
		ix = (int) ( (x / MACROBLOCK_GRID_RES));
		Verify (ix>=0);
		Verify (ix<m_MacroAllocWidth);
		Verify (iz>=0);
		Verify (iz<m_MacroAllocHeight);
		return(unsigned char) (m_MacroData[iz][ix]);
	}
	inline unsigned char CMoveGrid::MacroPassableLocal (int x,int z) const
	{
		Verify ((m_MacroAllocWidth!=0) && (m_MacroAllocHeight != 0));

		x += 32;
		z += 32;
//		x -= (int) (MinX/MACROBLOCK_GRID_RES);
//		z -= (int) (MinZ/MACROBLOCK_GRID_RES);
		Verify ((int) (x)>=0);
		Verify ((int) (z)>=0);
		Verify ((int) (x)<m_Width);
		Verify ((int) (z)<m_Height);
#if 0
		if ((int) (x)>=m_MacroAllocWidth)
			return 255;
		if ((int) (z)>=m_MacroAllocHeight)
			return 255;
		if ((int) (x)<0)
			return 255;
		if ((int) (z)<0)
			return 255;
#endif
		return(unsigned char) (m_MacroData[z][x]);
	}

	inline void CAirMoveGrid::Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned char canpass,bool override)		// in meters
	{
		x -= (MinX);
		z -= (MinZ);
		Verify (x>=0);
		Verify (z>=0);
		Verify (x<m_Width);
		Verify (z<m_Height);
#if 0
		if (x>=m_Width)
			return ;
		if (z>=m_Height)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif
		int ix,iz;

		iz = (int) (z / AIR_BLOCK_GRID_RES);
		ix = (int) (x / AIR_BLOCK_GRID_RES);
		Verify (ix>=0);
		Verify (ix<m_AllocWidth);
		Verify (iz>=0);
		Verify (iz<m_AllocHeight);
		if (override)
			m_Data[iz][ix] = 0;
		m_Data[iz][ix] |= canpass;
	}

	inline unsigned char CAirMoveGrid::Passable (Stuff::Scalar x,Stuff::Scalar z) const						// in meters
	{
		Verify ((m_Width!=0) && (m_Height != 0));
		x -= (MinX);
		z -= (MinZ);
		Verify ((int) (x)>=0);
		Verify ((int) (z)>=0);
		Verify ((int) (x)<m_Width);
		Verify ((int) (z)<m_Height);
#if 0
		if ((int) (x)>=m_Width)
			return -1;
		if ((int) (z)>=m_Height)
			return -1;
		if ((int) (x)<0)
			return -1;
		if ((int) (z)<0)
			return -1;
#endif

		int ix,iz;

		iz = (int) ( (z / AIR_BLOCK_GRID_RES));
		ix = (int) ( (x / AIR_BLOCK_GRID_RES));
		Verify (ix>=0);
		Verify (ix<m_AllocWidth);
		Verify (iz>=0);
		Verify (iz<m_AllocHeight);
		return(unsigned char) (m_Data[iz][ix]);
	}

	inline unsigned char CAirMoveGrid::PassableLocal (int x,int z) const						// in local
	{
		Verify ((m_AllocWidth!=0) && (m_AllocHeight != 0));

		x -= (int) (MinX/AIR_BLOCK_GRID_RES);
		z -= (int) (MinZ/AIR_BLOCK_GRID_RES);
		Verify (x>=0);
		Verify (x<m_AllocWidth);
		Verify (z>=0);
		Verify (z<m_AllocHeight);
#if 0
		if ((int) (x)>=m_AllocWidth)
			return -1;
		if ((int) (z)>=m_AllocHeight)
			return -1;
		if ((int) (x)<0)
			return -1;
		if ((int) (z)<0)
			return -1;
#endif
		return(unsigned char) (m_Data[z][x]);
	}
	inline void CAirMoveGrid::PassableLocal (int x,int z,unsigned char canpass,bool override)						// in local
	{
		Verify ((m_AllocWidth!=0) && (m_AllocHeight != 0));

		x -= (int) (MinX/AIR_BLOCK_GRID_RES);
		z -= (int) (MinZ/AIR_BLOCK_GRID_RES);
		Verify (x>=0);
		Verify (x<m_AllocWidth);
		Verify (z>=0);
		Verify (z<m_AllocHeight);
#if 0
		if (x>=m_AllocWidth)
			return ;
		if (z>=m_AllocHeight)
			return;
		if (x<0)
			return ;
		if (z<0)
			return;
#endif
		if (override)
			m_Data[z][x] = 0;
		m_Data[z][x] |= canpass;
	}

	inline void CAirMoveGrid::Destroy (void)
	{
		int i,size;

		size = m_AllocHeight;
		for (i=0;i<size;i++)
		{
			delete[] m_Data[i];
		}
		delete[] m_Data;
		m_Data = NULL;
	}
	inline void CAirMoveGrid::Construct (int width,int height)
	{
		if (m_Data)
		{
			Destroy ();
		}

		m_Width = width;
		m_Height = height;
		width /= AIR_BLOCK_GRID_RES;
		height /= AIR_BLOCK_GRID_RES;
		gos_PushCurrentHeap (g_RailHeap);
		m_Data = new unsigned char *[height];
		m_AllocHeight = height;
		m_AllocWidth = width;
		for (int i=0;i<height;i++)
		{
			m_Data[i] = new unsigned char[width];
		}
		gos_PopCurrentHeap ();
	}


	inline unsigned short CRailGraph::Passable (Stuff::Scalar x,Stuff::Scalar z) const
	{
		Verify (m_MoveGrid);
		return m_MoveGrid->Passable (x,z);
	}
	inline unsigned short CRailGraph::PassableLocal (int x,int z) const
	{
		Verify (m_MoveGrid);
		return m_MoveGrid->PassableLocal (x,z);
	}

	inline void CRailGraph::Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass)
	{
		Verify (m_MoveGrid);
		m_MoveGrid->Passable (x,z,canpass);
	}
	inline void CRailGraph::PassableLocal (int x,int z,unsigned short canpass)
	{
		Verify (m_MoveGrid);
		m_MoveGrid->PassableLocal (x,z,canpass);
	}
	inline void CRailGraph::PassableOverride (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass)
	{
		Verify (m_MoveGrid);
		m_MoveGrid->PassableOverride (x,z,canpass);
	}
	inline void CRailGraph::PassableLocalOverride (int x,int z,unsigned short canpass)
	{
		Verify (m_MoveGrid);
		m_MoveGrid->PassableLocalOverride (x,z,canpass);
	}
	inline unsigned char CRailGraph::MacroPassable (Stuff::Scalar x,Stuff::Scalar z) const
	{
		Verify (m_MoveGrid);
		return m_MoveGrid->MacroPassable (x,z);
	}

	inline unsigned char CRailGraph::MacroPassableLocal (int x,int z) const
	{
		Verify (m_MoveGrid);
		return m_MoveGrid->MacroPassableLocal (x,z);
	}

	inline unsigned char CRailGraph::AirPassable (Stuff::Scalar x,Stuff::Scalar z) const
	{
		Verify (m_AirMoveGrid);
		return m_AirMoveGrid->Passable (x,z);
	}
	inline unsigned char CRailGraph::AirPassableLocal (int x,int z) const
	{
		Verify (m_AirMoveGrid);
		return m_AirMoveGrid->PassableLocal (x,z);
	}

	inline void CRailGraph::AirPassable (Stuff::Scalar x,Stuff::Scalar z,unsigned char canpass,bool override)
	{
		Verify (m_AirMoveGrid);
		m_AirMoveGrid->Passable (x,z,canpass,override);
	}
	inline void CRailGraph::AirPassableLocal (int x,int z,unsigned char canpass,bool override)
	{
		Verify (m_AirMoveGrid);
		m_AirMoveGrid->PassableLocal (x,z,canpass,override);
	}

	inline int CRailGraph::AddLink (unsigned int n1,unsigned int n2,float weight[NUM_MOVE_TYPES][2],int moveflags[2])
	{
		CRailLink *temp;

		Verify ((n1>=0) && (n1<m_Nodes.size ()));
		Verify ((n2>=0) && (n2<m_Nodes.size ()));

		CRailNode *src,*dest;
		src = m_Nodes[n1];
		dest = m_Nodes[n2];
		Verify (src);
		Verify (dest);
		temp = src->LinkTo (dest);
		if (temp)
			return temp->ID ();

		gos_PushCurrentHeap (g_RailHeap);
		temp = new CRailLink (m_Nodes[n1],m_Nodes[n2],weight,moveflags);
		gos_PopCurrentHeap ();
		Register_Pointer (temp);
		m_Dirty = true;
		return AddLink (temp);
	}
	inline int CRailGraph::AddLink (CRailNode *n1,CRailNode *n2,float weight[NUM_MOVE_TYPES][2],int moveflags[2])
	{
		CRailLink *temp;
		int fred;

		Check_Pointer (n1);
		Check_Pointer (n2);
		temp = n1->LinkTo (n2);
		if (temp)
			return temp->ID ();

		fred = Connect (n1,n2);
		if (fred != -1)
			return fred;
		gos_PushCurrentHeap (g_RailHeap);
		temp = new CRailLink (n1,n2,weight,moveflags);
		gos_PopCurrentHeap ();
		Register_Pointer (temp);
		m_Dirty = true;
		return AddLink (temp);
	}

	inline int CRailGraph::CountNodes(void) const
	{
		int count;
		stlport::vector<CRailNode *>::const_iterator iter;

		count = 0;
		iter = m_Nodes.begin ();
		while (iter != m_Nodes.end ())
		{
			if (*iter)
				count++;
			iter++;
		}
		return count;
	}
	inline int CRailGraph::CountLinks(void) const
	{
		int count;
		stlport::vector<CRailLink *>::const_iterator iter;

		count = 0;
		iter = m_Links.begin ();
		while (iter != m_Links.end ())
		{
			if (*iter)
				count++;
			iter++;
		}
		return count;
	}
	inline CRailLink *CRailGraph::Link (unsigned int id)
	{
		Verify (id>=0);
		Verify (id<m_Links.size ());
		return m_Links[id];
	}
	inline CRailNode *CRailGraph::Node (unsigned int id)
	{
		Verify (id>=0);
		Verify (id<m_Nodes.size ());
		return m_Nodes[id];
	}
	inline void CRailGraph::DeleteNode (unsigned int id)
	{
		Verify (id>=0);
		Verify (id<m_Nodes.size ());
		unsigned int i;
		CRailNode *temp;

		temp = m_Nodes[id];
		if (temp)
		{
			for (i=0;i<m_Links.size ();i++)
			{
				if (!m_Links[i])
					continue;
				if (m_Links[i]->Location (0) == temp)
				{
					DeleteLink (i);
					continue;
				}
				if (m_Links[i]->Location (1) == temp)
				{
					DeleteLink (i);
					continue;
				}
			}
			RemoveBlock (id);
			delete m_Nodes[id];
			m_Nodes[id] = NULL;
		}
	}


	inline CRailPath::PathElement::PathElement (void)
	{
		loc = Stuff::Point3D (-1,-1,-1);
		usage = 0;
		onrail = false;
	}
	inline CRailPath::PathElement::PathElement (const Stuff::Point3D& p1,int p2,bool p3,int p4)
	{
		loc = p1;
		usage = p2;
		onrail = p3;
		linkid = p4;
	}
	inline bool CRailPath::PathElement::operator== (const PathElement& p1)
	{
		if (p1.loc != loc)
			return false;
		return true;
	}
	inline bool CRailPath::JumpSoon (void) const
	{
		if (!m_Calced)
			return false;
		int i;
		stlport::vector<PathElement>::iterator iter;
		iter = m_InPath;
		for (i=0;i<2;i++,iter++)
		{
			if (iter == m_Path.end ())
				return false;
			if (iter->usage & JUMPFLAG)
				return true;
		}
		return false;
	}
	inline int CRailPath::CurLink (void) const
	{
		if (!m_Calced)
			return -1;
		if (m_InPath == m_Path.end ())
			return -1;
		return m_InPath->linkid;
	}
	inline Stuff::Point3D CRailPath::NextPoint (void) const				// next link in path
	{
		stlport::vector<PathElement>::iterator iter;
		Stuff::Point3D pt(-1,-1,-1);

		if (!m_Calced)
			return Stuff::Point3D (-1,-1,-1);

		if (m_SubPath)
			pt = m_SubPath->NextPoint ();
		if (pt != Stuff::Point3D (-1,-1,-1))
			return pt;
		if ((m_InPath==m_Path.end () || (m_Path.size ()<=1)))
			return Stuff::Point3D (-1,-1,-1);
		iter = m_InPath;
		iter++;
		if (iter != m_Path.end ())
			return iter->loc;
		return Stuff::Point3D (-1,-1,-1);
	}
	inline Stuff::Point3D CGridPath::NextPoint (void) const				// next link in path
	{
		stlport::vector<DirElement>::iterator iter;

		if (!m_Calced)
			return Stuff::Point3D (-1,-1,-1);
		if (m_QuickValid)
			return Stuff::Point3D (-1,-1,-1);

		if ((m_InDirPath==m_DirList.end () || (m_DirList.size ()<=1)))
			return Stuff::Point3D (-1,-1,-1);
		iter = m_InDirPath;
		iter++;
		if (iter != m_DirList.end ())
		{
			Stuff::Scalar x;
			Stuff::Scalar z;
			x = (Stuff::Scalar) iter->locX*BLOCK_GRID_RES;
			z = (Stuff::Scalar) iter->locY*BLOCK_GRID_RES;
			x += BLOCK_GRID_RES/2.0f;
			z += BLOCK_GRID_RES/2.0f;
			return Stuff::Point3D (x,0,z);
		}
		return Stuff::Point3D (-1,-1,-1);
	}


	inline unsigned int CGridPath::Cost (int sx,int sy)
	{
		if (sx-m_BlockOriginX < 0)
			return 0;
		if (sy-m_BlockOriginY < 0)
			return 0;
		if (sx-m_BlockOriginX >= BLOCK_GRID_SIZE)
			return 0 ;
		if (sy-m_BlockOriginY >= BLOCK_GRID_SIZE)
			return 0;

		return m_BlockGrid[sx-m_BlockOriginX][sy-m_BlockOriginY][0];
	}
	inline unsigned int CGridPath::Estimate (int sx,int sy)
	{
		if (sx-m_BlockOriginX < 0)
			return 0;
		if (sy-m_BlockOriginY < 0)
			return 0;
		if (sx-m_BlockOriginX >= BLOCK_GRID_SIZE)
			return 0;
		if (sy-m_BlockOriginY >= BLOCK_GRID_SIZE)
			return 0;


		return m_BlockGrid[sx-m_BlockOriginX][sy-m_BlockOriginY][1];
	}
	inline bool CGridPath::Cost (int sx,int sy,unsigned int cost,unsigned int estimate)
	{
		if (sx-m_BlockOriginX < 0)
			return false;
		if (sy-m_BlockOriginY < 0)
			return false;
		if (sx-m_BlockOriginX >= BLOCK_GRID_SIZE)
			return false;
		if (sy-m_BlockOriginY >= BLOCK_GRID_SIZE)
			return false;


		if ((Cost (sx,sy) != 0) && ((Cost(sx,sy)+Estimate (sx,sy)) < (cost+estimate)))
			return false;
		m_BlockGrid[sx-m_BlockOriginX][sy-m_BlockOriginY][0] = cost;
		m_BlockGrid[sx-m_BlockOriginX][sy-m_BlockOriginY][1] = estimate;
		return true;
	}

	inline int CGridPath::CostGuess (int sx,int sy)
	{
		int t1,t2;

		t1 = (int) (m_EndX/BLOCK_GRID_RES) - sx;
		t2 = (int) (m_EndY/BLOCK_GRID_RES) - sy;

		t1 = t1<0 ? t1*-1 : t1;
		t2 = t2<0 ? t2*-1 : t2;

		return(10*(t2 < t1 ? (t1+(t2/2)) : (t2+(t1/2))));
	}

	inline bool CGridPath::Next (void)							// true if path still exists
	{
		if (m_InDirPath != m_DirList.end ())
		{
			m_InDirPath++;
			return(m_InDirPath != m_DirList.end ());
		}
		return false;
	}
	inline bool CGridPath::OneFromEnd (void) const			// at end is also good
	{
		stlport::vector<DirElement>::iterator iter;

		iter = m_InDirPath;
		if (iter != m_DirList.end ())
		{
			iter++;
			return iter == m_DirList.end ();
		}
		return iter == m_DirList.end ();
	}
	inline Stuff::Point3D CGridPath::CurrentPoint (void) const
	{
		Verify (!m_QuickValid);
		Stuff::Scalar x;
		Stuff::Scalar z;
		x = (Stuff::Scalar) m_InDirPath->locX*BLOCK_GRID_RES;
		z = (Stuff::Scalar) m_InDirPath->locY*BLOCK_GRID_RES;
		if (x < 0)
			x -= BLOCK_GRID_RES/2.0f;
		else
			x += BLOCK_GRID_RES/2.0f;
		if (z < 0)
			z -= BLOCK_GRID_RES/2.0f;
		else
			z += BLOCK_GRID_RES/2.0f;
		return Stuff::Point3D (x,0,z);
	}
/*
		inline CGridPath::GridPathElement CGridPath::Element (int index)
		{
			Verify (index >= 0);
			Verify (index < m_Path.size ());
			return m_GridPath[index];
		}
*/
	inline CGridPath::DirElement CGridPath::direlement (int index)
	{
		Verify (index >= 0);
		Verify (index < m_DirList.size ());
		return m_DirList[index];
	}

	inline CRailPath *CPathRequest::DetachNodePath (void)
	{
		CRailPath *toret = m_NodePath;
		m_NodePath = NULL;
		return toret;
	}
	inline CGridPath *CPathRequest::DetachGridPath (void)
	{
		CGridPath *toret = m_GridPath;
		m_GridPath = NULL;
		return toret;
	}

	inline bool CheckCanPass (unsigned int flags, unsigned int mask)
	{
//		if (mask & PLANEPASS_FLAG)
//			return false;
#pragma warning (disable : 4800)
		return((flags&~BRIDGE_FLAG)  & mask);
#pragma warning (default : 4800)
	}

	inline int ConvertTypetoUsage (int movetype)
	{
		switch (movetype)
		{
			case MechWarrior4::MWObject__GameModel::LEG_MOVETYPE:
				return LEGFLAG;
			case MechWarrior4::MWObject__GameModel::LEGJUMP_MOVETYPE:
				return LEGFLAG + JUMPFLAG;
			case MechWarrior4::MWObject__GameModel::TRACK_MOVETYPE:
				return TRACKFLAG;
			case MechWarrior4::MWObject__GameModel::WHEEL_MOVETYPE:
				return WHEELFLAG;
			case MechWarrior4::MWObject__GameModel::FLYER_MOVETYPE:
				return FLYFLAG;
			case MechWarrior4::MWObject__GameModel::HOVER_MOVETYPE:
				return HOVERFLAG;
			case MechWarrior4::MWObject__GameModel::HELI_MOVETYPE:
				return HELIFLAG;
			case MechWarrior4::MWObject__GameModel::WATER_MOVETYPE:
				return WATERFLAG;
			default:
				gosASSERT (false);
				return 0;
		}
//		return 0;
	}

	inline int ConvertUsagetoMovePass (int usage)
	{
		int toret;
		toret = 0;

		if (usage & BRIDGEFLAG)
			toret = BRIDGE_FLAG;
		if (usage & LEGFLAG)
			toret += LEGPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & JUMPFLAG)
			toret += JUMPPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & TRACKFLAG)
			toret += TRACKPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & WHEELFLAG)
			toret += WHEELPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & FLYFLAG)
			toret += JUMPPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & HOVERFLAG)
			toret += HOVERPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & HELIFLAG)
			toret += JUMPPASS_FLAG|MOVEPASSNOW_FLAG;
		else if (usage & WATERFLAG)
			toret += WATERPASS_FLAG|MOVEPASSNOW_FLAG;
		else
			gosREPORT (false,"unknown usage passed into ConvertUsageToMovePass");

		return toret;
	}
}




