Files
firestorm/Gameleap/code/mw4/Code/AI test/map.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

868 lines
16 KiB
C++

#pragma warning (disable:4786)
#include <utils\utils.h>
#include "map.hpp"
#include "move.hpp"
MAPELEMENT g_Map[MAPSIZE][MAPSIZE];
void GenMap (MAPELEMENT map[MAPSIZE][MAPSIZE],int x1,int y1,int x2,int y2);
void InitMap (void)
{
int x,y;
for (y=0;y<MAPSIZE;y++)
for (x=0;x<MAPSIZE;x++)
{
g_Map[x][y].passable = true;
g_Map[x][y].weight = 0.0;
}
for (y=0;y<MAPSIZE;y++)
{
g_Map[0][y].passable = false;
g_Map[MAPSIZE-1][y].passable = false;
}
for (x=0;x<MAPSIZE;x++)
{
g_Map[x][0].passable = false;
g_Map[x][MAPSIZE-1].passable = false;
}
g_Map[0][0].weight = 0.5f;
g_Map[MAPSIZE-1][0].weight = 0.5f;
g_Map[0][MAPSIZE-1].weight = 0.5f;
g_Map[MAPSIZE-1][MAPSIZE-1].weight = 0.5f;
GenMap (g_Map,0,0,MAPSIZE-1,MAPSIZE-1);
for (y=0;y<MAPSIZE;y++)
for (x=0;x<MAPSIZE;x++)
{
if (g_Map[x][y].weight > 0.75)
g_Map[x][y].passable = false;
g_Map[x][y].weight+=1.0;
g_Map[x][y].weight *= 5.0;
}
InitMoveData ();
}
void RenderEdges (CDIBSurface& dest,int dx)
{
int x,y;
for (y=0;y<MAPCELLCOUNT;y++)
for (x=0;x<MAPCELLCOUNT;x++)
{
g_MapCells[x][y].RenderEdges (dest,dx);
}
}
int SquareInfo (int x,int y)
{
return Passable (x,y);
}
void GenMap (MAPELEMENT map[MAPSIZE][MAPSIZE],int x1,int y1,int x2,int y2)
{
int midx,midy;
double v1,v2,v3,v4;
double rmax;
if (x2 <= x1)
return;
if (y2 <= y1)
return;
midx = (x1+x2)/2;
midy = (y1+y2)/2;
rmax = RAND_MAX;
if (map[midx][y1].weight == 0.0)
{
v1 = map[midx][y1].weight = ((map[x1][y1].weight + map[x2][y1].weight) / 2.0) + (((rand()/rmax)-0.5)*((x2-x1)/MAPX));
if (v1<0)
map[midx][y1].weight = 0;
if (v1 > 1.0)
map[midx][y1].weight = 1.0;
}
else v1 = map[midx][y1].weight;
if (map[midx][y2].weight ==0.0)
{
v2 = map[midx][y2].weight = ((map[x1][y2].weight + map[x2][y2].weight) / 2.0) + (((rand()/rmax)-0.5)*((x2-x1)/MAPX));
if (v2<0)
map[midx][y2].weight = 0;
if (v2 > 1.0)
map[midx][y2].weight = 1.0;
}
else v2 = map[midx][y2].weight;
if (map[x1][midy].weight == 0.0)
{
v3 = map[x1][midy].weight = ((map[x1][y1].weight + map[x1][y2].weight) / 2.0) + (((rand()/rmax)-0.5)*((y1-y2)/MAPY));
if (v3<0)
map[x1][midy].weight = 0;
if (v3 > 1.0)
map[x1][midy].weight = 1.0;
}
else v3 = map[x1][midy].weight;
if (map[x2][midy].weight == 0.0)
{
v4 = map[x2][midy].weight = ((map[x2][y1].weight + map[x2][y2].weight) / 2.0) + (((rand()/rmax)-0.5)*((y1-y2)/MAPY));
if (v4<0)
map[x2][midy].weight = 0;
if (v4 > 1.0)
map[x2][midy].weight = 1.0;
}
else v4 = map[x2][midy].weight;
if (map[midx][midy].weight == 0.0)
{
map[midx][midy].weight = ((v1+v2+v3+v4)/4.0) + 2*(((rand()/rmax)-0.5)*((y1-y2)/MAPY));
if (map[midx][midy].weight<0)
map[midx][midy].weight = 0;
if (map[midx][midy].weight > 1.0)
map[midx][midy].weight = 1.0;
}
/*
if (midx == x1)
return;
if (midx == x2)
return;
if (midy == y1)
return;
if (midy == y2)
return;
*/
if ((midx != x2) && (midx != x1))
{
GenMap (map,x1,y1,midx,midy);
GenMap (map,midx,y1,x2,midy);
}
if ((midy != y1) && (midy != y2))
{
GenMap (map,x1,midy,midx,y2);
GenMap (map,midx,midy,x2,y2);
}
}
/*
float GetOneCost (int sx,int sy,int dx,int dy)
{
int deltax,deltay;
float toret;
if (!Passable (dx,dy))
return -1;
toret = abs (g_Map[sx][sy].weight - g_Map[dx][dy].weight)+1;
// toret *= 0.5;
return toret;
deltax = dx - sx;
deltay = dy - sy;
if (deltax == 0)
return toret*0.5;
if (deltay == 0)
return toret*0.5;
return toret * 0.75;
}
*/
/*
CMapNode::CMapNode (void)
{
m_Left = NULL;
m_Right = NULL;
m_Bottom = NULL;
m_Top = NULL;
int i;
for (i=0;i<PASS_NUM;i++)
{
m_Passable[i] = true;
}
m_PassAverage = 0;
m_WeightAverage = 0;
m_MapQuad = NULL;
m_MapQuad = new CMapQuadNode (NULL,this);
m_MapQuad->Left (0);
m_MapQuad->Top (0);
m_MapQuad->Right (MAPSIZE-1);
m_MapQuad->Bottom (MAPSIZE-1);
m_MapQuad->SubDivide ();
}
CMapNode::~CMapNode (void)
{
delete m_Left;
delete m_Right;
delete m_Bottom;
delete m_Top;
}
void CMapNode::RenderData (CDIBSurface& dest,int dx)
{
m_MapQuad->RenderData (dest,dx);
}
void CMapNode::RenderEdges (CDIBSurface& dest,int dx)
{
m_MapQuad->RenderEdges (dest,dx);
}
CMapQuadNode::CMapQuadNode (CMapQuadNode *parent,CMapNode *root)
{
m_Root = root;
m_Parent = parent;
m_Left = m_Right = m_Bottom = m_Top = 0;
m_Child[0] = NULL;
m_Child[1] = NULL;
m_Child[2] = NULL;
m_Child[3] = NULL;
int i;
for (i=0;i<PASS_NUM;i++)
{
m_Passable[i] = true;
}
m_PassAverage = 0;
m_WeightAverage = 0;
}
CMapQuadNode::~CMapQuadNode (void)
{
}
void CMapQuadNode::RenderData (CDIBSurface& dest,int dx)
{
const int CELLSIZE=2;
if (m_Child[0])
{
m_Child[0]->RenderData (dest,dx);
m_Child[1]->RenderData (dest,dx);
m_Child[2]->RenderData (dest,dx);
m_Child[3]->RenderData (dest,dx);
}
else
{
int color = 255.0 * ((m_WeightAverage/5.0)-1.0);
dest.Fill (dx+m_Left*CELLSIZE,m_Top*CELLSIZE,dx+(m_Right+1)*CELLSIZE,(m_Bottom+1)*CELLSIZE,RGB (color,color,color));
}
}
void CMapQuadNode::RenderEdges (CDIBSurface& dest,int dx)
{
const int CELLSIZE=2;
if (m_Child[0])
{
m_Child[0]->RenderEdges (dest,dx);
m_Child[1]->RenderEdges (dest,dx);
m_Child[2]->RenderEdges (dest,dx);
m_Child[3]->RenderEdges (dest,dx);
}
else
{
int x,y;
for (x=m_Left;x<m_Right;x++)
{
dest.Fill (dx+x*CELLSIZE,m_Top*CELLSIZE,dx+(x+1)*CELLSIZE,(m_Top+1)*CELLSIZE,RGB (0,255,0));
// dest.Fill (x*CELLSIZE,m_Bottom*CELLSIZE,(x+1)*CELLSIZE,(m_Bottom+1)*CELLSIZE,RGB (0,255,0));
}
for (y=m_Top;y<m_Bottom;y++)
{
dest.Fill (dx+m_Left*CELLSIZE,y*CELLSIZE,dx+(m_Left+1)*CELLSIZE,(y+1)*CELLSIZE,RGB (0,255,0));
// dest.Fill (m_Right*CELLSIZE,y*CELLSIZE,(m_Right+1)*CELLSIZE,(y+1)*CELLSIZE,RGB (0,255,0));
}
}
}
bool CMapQuadNode::SubDivide (void)
{
int midx,midy,count;
bool flag;
flag = true;
if ((m_Right-m_Left)<=MAXDEPTH)
flag = false;
if ((m_Bottom-m_Top)<=MAXDEPTH)
flag = false;
assert (m_Left>=0);
assert (m_Top>=0);
assert (m_Right <=MAPSIZE);
assert (m_Bottom <= MAPSIZE);
assert (m_Left < m_Right);
assert (m_Bottom > m_Top);
midy = (m_Bottom-m_Top+1)/2;
midx = (m_Right-m_Left+1)/2;
if (flag)
{
m_Child[0] = new CMapQuadNode (this,m_Root);
m_Child[1] = new CMapQuadNode (this,m_Root);
m_Child[2] = new CMapQuadNode (this,m_Root);
m_Child[3] = new CMapQuadNode (this,m_Root);
m_Child[TOPLEFT_CHILD]->SetSize (m_Left,m_Top,m_Left+midx,m_Top+midy);
m_Child[BOTTOMLEFT_CHILD]->SetSize (m_Left,m_Top+midy+1,m_Left+midx,m_Bottom);
m_Child[TOPRIGHT_CHILD]->SetSize (m_Left+midx+1,m_Top,m_Right,m_Top+midy);
m_Child[BOTTOMRIGHT_CHILD]->SetSize (m_Left+midx+1,m_Top+midy+1,m_Right,m_Bottom);
m_Child[0]->SubDivide ();
m_Child[1]->SubDivide ();
m_Child[2]->SubDivide ();
m_Child[3]->SubDivide ();
}
else
{
m_Child[0] = NULL;
m_Child[1] = NULL;
m_Child[2] = NULL;
m_Child[3] = NULL;
}
m_PassAverage = 0;
m_WeightAverage = 0;
count = 0;
for (midx = m_Left;midx<=m_Right;midx++)
{
for (midy=m_Top;midy<=m_Bottom;midy++)
{
count++;
m_WeightAverage+=g_Map[midx][midy].weight;
if (g_Map[midx][midy].passable)
{
m_PassAverage++;
}
}
}
m_PassAverage /= count;
m_WeightAverage /= count;
return true;
}
*/
#if 0
double CMapQuadNode::CalcAverageCostSplit (int where,bool left )
{
int x,y,z;
int lx,hx,ly,hy;
double current;
int count;
assert (where < (m_LeftSplit?m_Bottom:m_Right));
assert (where > (m_LeftSplit?m_Top:m_Left));
assert (m_Left>=0);
assert (m_Top>=0);
assert (m_Right <=MAPSIZE);
assert (m_Bottom <= MAPSIZE);
assert (m_Left < m_Right);
assert (m_Bottom > m_Top);
if (m_LeftSplit)
{
lx = m_Left;
hx = m_Right;
if (left)
{
ly = m_Top;
hy = m_Top+where;
}
else
{
ly = m_Top+where+1;
hy = m_Bottom;
}
}
else
{
ly = m_Top;
hy = m_Bottom;
if (left)
{
lx = m_Left;
hx = m_Left+where;
}
else
{
lx = m_Left+where+1;
hx = m_Right;
}
}
count = 0;
current = 0.0;
for (x=lx;x<=hx;x++)
{
for (y=ly;y<=hy;y++)
{
for (z=0;z<OFFSIZE;z++)
{
double cost;
cost = g_MapTree->GetOneCost (x,y,x+offset[z][0],y+offset[z][1]);
if (cost < 0)
cost = 10000.0;
current+=cost;
count++;
}
}
}
return current / ((double)count);
}
double CMapQuadNode::AnalyzeSplit (int where,bool left)
{
double average;
int x,y,z;
int lx,hx,ly,hy;
double current;
int count;
assert (where < (m_LeftSplit?m_Bottom:m_Right));
assert (where > (m_LeftSplit?m_Top:m_Left));
assert (m_Left>=0);
assert (m_Top>=0);
assert (m_Right <=MAPSIZE);
assert (m_Bottom <= MAPSIZE);
assert (m_Left < m_Right);
assert (m_Bottom > m_Top);
average = CalcAverageCostSplit (where,left);
if (m_LeftSplit)
{
lx = m_Left;
hx = m_Right;
if (left)
{
ly = m_Top;
hy = m_Top+where;
}
else
{
ly = m_Top+where+1;
hy = m_Bottom;
}
}
else
{
ly = m_Top;
hy = m_Bottom;
if (left)
{
lx = m_Left;
hx = m_Left+where;
}
else
{
lx = m_Left+where+1;
hx = m_Right;
}
}
count = 0;
current = 0.0;
for (x=lx;x<=hx;x++)
{
for (y=ly;y<=hy;y++)
{
for (z=0;z<OFFSIZE;z++)
{
double cost = g_MapTree->GetOneCost (x,y,x+offset[z][0],y+offset[z][1]);
if (cost < 0)
cost = 10000.0;
current+= ((cost-average) * (cost-average));
count++;
}
}
}
return current / ((double)count);
}
int CMapQuadNode::ChooseSplit (void)
{
int mid,min;
double minvalue;
double temp;
double splits[MAPSIZE][2];
double cost[MAPSIZE];
assert (m_Left>=0);
assert (m_Top>=0);
assert (m_Right <=MAPSIZE);
assert (m_Bottom <= MAPSIZE);
assert (m_Left < m_Right);
assert (m_Bottom > m_Top);
for (mid = 0;mid<MAPSIZE;mid++)
{
splits[mid][0] = 0.0;
splits[mid][1] = 0.0;
}
min = -1;
minvalue = DBL_MAX;
if (m_LeftSplit)
{
for (mid = (m_Top+MAXDEPTH4);mid<=(m_Bottom-MAXDEPTH4);mid++)
{
splits[mid][0] = AnalyzeSplit (mid,0);
splits[mid][1] = AnalyzeSplit (mid,1);
cost[mid] = splits[mid][0] + splits[mid][1];
temp = ((double)(mid-m_Top)/(double) (m_Bottom - m_Top));
temp *= PI;
// temp -= (PI/2.0);
temp = sin(temp);
temp = 1.0 - temp;
cost[mid] *= temp;
if (cost[mid] < minvalue)
{
min = mid;
minvalue = cost[mid];
}
}
}
else
{
for (mid = (m_Left+MAXDEPTH4);mid<=(m_Right-MAXDEPTH4);mid++)
{
splits[mid][0] = AnalyzeSplit (mid,0);
splits[mid][1] = AnalyzeSplit (mid,1);
cost[mid] = splits[mid][0] + splits[mid][1];
temp = ((double)(mid-m_Left)/(double) (m_Right - m_Left));
temp *= PI;
// temp -= (PI/2.0);
temp = sin(temp);
temp = 1.0 - temp;
cost[mid] *= temp;
// temp = (((mid-m_Left)/(m_Right - m_Left)) * PI)-(PI/2.0);
// temp = 1.0 - sin (temp);
cost[mid] *= temp;
if (cost[mid] < minvalue)
{
min = mid;
minvalue = cost[mid];
}
}
}
if (min < 0)
{
if (m_LeftSplit)
mid = (m_Bottom-m_Top+1)/2;
else
mid = (m_Right-m_Left+1)/2;
}
else
mid = min;
assert (mid < (m_LeftSplit?m_Bottom:m_Right));
assert (mid > (m_LeftSplit?m_Top:m_Left));
return mid;
}
bool CMapNode::CalcPath (std::stack<PATHELEMENT> *dest,CPoint start,CPoint end,int depth,bool followshort)
{
int i,j;
FibHeap calc;
CALCELEMENT *temp;
CALCELEMENT *shortdes = NULL;
int lastdepth;
int x=-1,y=-1;
bool done;
while (!dest->empty ())
dest->pop ();
for (i=0;i<MAPSIZE;i++)
{
for (j=0;j<MAPSIZE;j++)
{
pathmap[i][j] = 0;
}
}
temp = new CALCELEMENT (start.x,start.y);
pathmap[start.x][start.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,end.x,end.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 == end.x) && (y == end.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 = end.x;
cury = end.y;
}
dest->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);
dest->push (PATHELEMENT (curx+offset[min][0],cury+offset[min][1]));
if (((curx+offset[min][0]) == start.x) && ((cury+offset[min][1]) == start.y))
{
done = true;
continue;
}
curx += offset[min][0];
cury += offset[min][1];
}
// m_CurPath.push (PATHELEMENT (curdes.x,curdes.y));
return true;
}
#endif
#if 0
int i,j;
FibHeap calc;
CALCELEMENT *temp;
CALCELEMENT *shortdes = NULL;
int lastdepth;
int x=-1,y=-1;
bool done;
while (!dest->empty ())
dest->pop ();
for (i=0;i<MAPSIZE;i++)
{
for (j=0;j<MAPSIZE;j++)
{
pathmap[i][j] = 0;
}
}
temp = new CALCELEMENT (start.x,start.y);
pathmap[start.x][start.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,end.x,end.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 == end.x) && (y == end.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 = end.x;
cury = end.y;
}
dest->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);
dest->push (PATHELEMENT (curx+offset[min][0],cury+offset[min][1]));
if (((curx+offset[min][0]) == start.x) && ((cury+offset[min][1]) == start.y))
{
done = true;
continue;
}
curx += offset[min][0];
cury += offset[min][1];
}
// m_CurPath.push (PATHELEMENT (curdes.x,curdes.y));
return true;
#endif