Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
352 lines
6.5 KiB
C++
352 lines
6.5 KiB
C++
#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;i<size;i++)
|
|
{
|
|
temp = m_CurrentMembers.front();
|
|
m_CurrentMembers.pop();
|
|
m_CurrentMembers.push (temp);
|
|
// temp.member->SetFormationDes (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;i<MAPSIZE;i++)
|
|
{
|
|
for (j=0;j<MAPSIZE;j++)
|
|
{
|
|
pathmap[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
temp = new CALCELEMENT (Location().x,Location().y);
|
|
pathmap[Location().x][Location().y] = 1;
|
|
calc.Insert (temp);
|
|
|
|
done = false;
|
|
lastdepth = 0;
|
|
while (!done && ((depth == -1)||(depth<lastdepth)))
|
|
{
|
|
temp = (CALCELEMENT *) calc.ExtractMin ();
|
|
if (temp == NULL)
|
|
break;
|
|
lastdepth = pathmap[temp->x][temp->y];
|
|
for (i=0;i<OFFSIZE;i++)
|
|
{
|
|
x = offset[i][0] + temp->x;
|
|
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<OFFSIZE;i++)
|
|
{
|
|
x = offset[i][0] + curx;
|
|
y = offset[i][1] + cury;
|
|
if (x < 0)
|
|
continue;
|
|
if (x >= 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<CALCELEMENT> 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> 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
|