Files
firestorm/Gameleap/code/mw4/Code/AI test/ai formation.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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