#pragma warning (disable:4786) #include "ai formation.hpp" #include "globals.hpp" extern float pathmap[MAPSIZE][MAPSIZE]; bool Passable (int dx,int dy); AIFormation::AIFormation (void) { m_Location.x = 1; m_Location.y = 1; } AIFormation::~AIFormation (void) { } bool AIFormation::AddAI (AI *newai) { AIMove *temp; temp = newai->Move (); if (!temp) return false; return temp->JoinFormation (*this); } bool AIFormation::AddMove (AIMove *newmove) { FormationData temp; temp.member = newmove; temp.dx = 1; temp.dy = 1; m_CurrentMembers.push (temp); return true; } void AIFormation::SetDestination (int x,int y) { curdes.x = x; curdes.y = y; newdes = true; } bool AIFormation::Think (double value) { if (newdes) { if (!g_Map[curdes.x][curdes.y].passable) return false; newdes = false; if (!CalcPath (-1,true)) return false; } if (m_CurPath.empty()) return false; int i,size; FormationData temp; PATHELEMENT path = m_CurPath.top(); m_CurPath.pop (); size = m_CurrentMembers.size(); for (i=0;iSetFormationDes (path.x,path.y); temp.member->Parent ()->Think (value); } // m_Location.x = path.x; // m_Location.y = path.y; return true; } float AIFormation::GetOneCost (int sx,int sy,int dx,int dy) { int deltax,deltay; if (!Passable (dx,dy)) return -1; deltax = dx - sx; deltay = dy - sy; if (deltax == 0) return 1; if (deltay == 0) return 1; return 1.5f; } float AIFormation::PathCostGuess (int sx,int sy,int dx,int dy) { int t1,t2; t1 = dx - sx; t2 = dy - sy; __asm { mov eax,t1 cdq xor eax,edx sub eax,edx mov t1,eax mov eax,t2 cdq xor eax,edx sub eax,edx mov t2,eax } if (t1 == 0) return t2; if (t2 == 0) return t1; if ((t1 == 0) && (t2 == 0)) return 0; float f1,f2; f1 = t1; f2 = t2; return f2 < f1 ? (f1+(f2/2.0)) : (f2+(f1/2.0)); } bool AIFormation::CalcPath (int depth,bool followshort) { #if 0 int i,j; FibHeap calc; CALCELEMENT *temp; CALCELEMENT *shortdes = NULL; const int OFFSIZE = 8; int lastdepth; int offset[OFFSIZE][2] = { {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1} }; int x=-1,y=-1; bool done; while (!m_CurPath.empty ()) m_CurPath.pop (); for (i=0;ix][temp->y]; for (i=0;ix; y = offset[i][1] + temp->y; float cost = GetOneCost (temp->x,temp->y,x,y); if (cost == -1) continue; cost += PathCostGuess (x,y,curdes.x,curdes.y); if ((pathmap[x][y] == 0) || (pathmap[x][y] > (pathmap[temp->x][temp->y]+cost))) { pathmap[x][y] = pathmap[temp->x][temp->y]+cost; calc.Insert (new CALCELEMENT(x,y)); } if ((x == curdes.x) && (y == curdes.y)) { done = true; break; } } delete temp; } if ((!done) && (depth != -1) && (depth>=lastdepth) && followshort) { shortdes = (CALCELEMENT *) calc.ExtractMin (); if (shortdes) done = true; } while (temp = (CALCELEMENT *) calc.ExtractMin ()) delete temp; if (!done) return false; done = false; int curx,cury,min; if (shortdes) { curx = shortdes->x; cury = shortdes->y; delete shortdes; } else { curx = curdes.x; cury = curdes.y; } m_CurPath.push (PATHELEMENT (curx,cury)); min = -1; while (!done) { min = -1; assert (pathmap[curx][cury] != 0); for (i=0;i= MAPSIZE) continue; if (y < 0) continue; if (y >= MAPSIZE) continue; if (pathmap[x][y] == 0) continue; if (pathmap[x][y] < pathmap[curx][cury]) { if (min == -1) min = i; else { if (pathmap[x][y] < pathmap[curx+offset[min][0]][cury+offset[min][1]]) min = i; } } } assert (min != -1); m_CurPath.push (PATHELEMENT (curx+offset[min][0],cury+offset[min][1])); if (((curx+offset[min][0]) == Location().x) && ((cury+offset[min][1]) == Location ().y)) { done = true; continue; } curx += offset[min][0]; cury += offset[min][1]; } #endif return true; } /* bool PATHELEMENT::operator< (const PATHELEMENT& p1) const { if (p1.x < x) return false; if (x < p1.x) return true; if (p1.y < y) return false; if (y < p1.y) return true; return true; } bool PATHELEMENT::operator== (const PATHELEMENT& p1) const { if ((p1.x == x) && (p1.y == y)) return true; return false; } */ #if 0 class CALCELEMENT : public FibHeapNode { private: static FixedHeap m_EmptyCalcElement; public: int x,y; CALCELEMENT (int nx,int ny) { x = nx; y = ny;} CALCELEMENT (void) { x = -1; y = -1; } virtual void operator =(FibHeapNode& RHS); virtual bool operator ==(FibHeapNode& RHS); virtual bool operator <(FibHeapNode& RHS); // static CALCELEMENT *GetBlankElement (void) { return (CALCELEMENT *) m_EmptyCalcElement.Alloc (); } // static void DoneElement (CALCELEMENT *oldelem) { m_EmptyCalcElement.Free (oldelem); } // void *operator new (size_t size) {return GetBlankElement (); } // void operator delete (void *value,size_t size) { DoneElement ((CALCELEMENT *) value); } }; //FixedHeap CALCELEMENT::m_EmptyCalcElement(1); void CALCELEMENT::operator =(FibHeapNode& RHS) { CALCELEMENT& fred = (CALCELEMENT&) RHS; x = fred.x; y = fred.y; } bool CALCELEMENT::operator ==(FibHeapNode& RHS) { CALCELEMENT& fred = (CALCELEMENT&) RHS; if (x != fred.x) return false; if (y != fred.y) return false; return true; } bool CALCELEMENT::operator <(FibHeapNode& RHS) { CALCELEMENT& fred = (CALCELEMENT&) RHS; if (pathmap[x][y] < pathmap[fred.x][fred.y]) return true; if (pathmap[x][y] > pathmap[fred.x][fred.y]) return false; if (fred.x < x) return false; if (x < fred.x) return true; if (fred.y < y) return false; if (y < fred.y) return true; return true; } #endif