#pragma warning (disable:4786) #include #include "map.hpp" #include "move.hpp" #include "movezone.hpp" #include CMapCell g_MapCells[MAPCELLCOUNT][MAPCELLCOUNT]; std::map pathmapzone[MAPCELLCOUNT][MAPCELLCOUNT][2]; // index is for the topleft cell of each src,dest pair the 2 is for the offset table-2 bool SetWeight (int sx,int sy,int offset,int areaentry,int areaexit,float newweight) { int ix,iy,io; int index; int temp; std::map::iterator iter; ix = sx; iy = sy; io = offset; switch (offsetzone[offset][2]) { case 0: ix--; temp = areaentry; areaentry = areaexit; areaexit = temp; break; case 1: iy--; temp = areaentry; areaentry = areaexit; areaexit = temp; break; case 2: io-=2; break; case 3: io-=2; break; } assert (ix>=0); assert (ix=0); assert (iy=0); assert (io<2); index = areaentry<<4; index += areaexit; iter = pathmapzone[ix][iy][io].find (index); if (iter == pathmapzone[ix][iy][io].end ()) { pathmapzone[ix][iy][io][index] = newweight; return true; } if ((*iter).second > newweight) { pathmapzone[ix][iy][io][index] = newweight; return true; } return false; } float GetWeight (int sx,int sy,int dx,int dy,int areaentry,int areaexit) { if (abs (sx-dx)) { if (sx > dx) return GetWeight (sx,sy,0,areaentry,areaexit); else return GetWeight (sx,sy,2,areaentry,areaexit); } else if (abs(sy-dy)) { if (sy > dy) return GetWeight (sx,sy,1,areaentry,areaexit); else return GetWeight (sx,sy,3,areaentry,areaexit); } assert (false); return -1.0; } float GetWeight (int sx,int sy,int offset,int areaentry,int areaexit) { int ix,iy,io; int index; int temp; std::map::iterator iter; ix = sx; iy = sy; io = offset; switch (offsetzone[offset][2]) { case 0: ix--; temp = areaentry; areaentry = areaexit; areaexit = temp; break; case 1: iy--; temp = areaentry; areaentry = areaexit; areaexit = temp; break; case 2: io-=2; break; case 3: io-=2; break; } if (ix<0) return -1; if (ix>=MAPCELLCOUNT) return -1; if (iy<0) return -1; if (iy>=MAPCELLCOUNT) return -1; assert (io>=0); assert (io<2); index = areaentry<<4; index += areaexit; iter = pathmapzone[ix][iy][io].find (index); if (iter == pathmapzone[ix][iy][io].end ()) { return -1.0; } return (*iter).second; } void InitMoveZoneData (void) { int curx,cury; int x,y; for (y=0,cury = 0;y (0,curx,MAPSIZE-1); right = clamp (0,left+MAPCELLSIZE-1,MAPSIZE-1); top = clamp (0,cury,MAPSIZE-1); bottom = clamp (0,top+MAPCELLSIZE-1,MAPSIZE-1); g_MapCells[x][y].SetSize (left,top,right,bottom); } for (y=0;y=MAPCELLSIZE) return; if (sy>=MAPCELLSIZE) return; if ((m_Areas[sx][sy] == 0) && (SquareInfo (sx+m_Left,sy+m_Top)==info)) { m_Areas[sx][sy] = id; CalcArea (sx-1,sy,id,info); CalcArea (sx+1,sy,id,info); CalcArea (sx,sy-1,id,info); CalcArea (sx,sy+1,id,info); } } void CMapCell::CalcInterior (void) { int x,y,id; float count[MAXAREAS]; for (x=0;x CALCZONEELEMENT::m_EmptyCalcZoneElement(1); void CALCZONEELEMENT::operator =(FibHeapNode& RHS) { CALCZONEELEMENT& fred = (CALCZONEELEMENT&) RHS; sx = fred.sx; sy = fred.sy; dx = fred.dx; dy = fred.dy; sarea = fred.sarea; darea = fred.darea; dir = fred.dir; } bool CALCZONEELEMENT::operator ==(FibHeapNode& RHS) { CALCZONEELEMENT& fred = (CALCZONEELEMENT&) RHS; if (sx != fred.sx) return false; if (sy != fred.sy) return false; if (dx != fred.dx) return false; if (dy != fred.dy) return false; if (sarea != fred.sarea) return false; if (darea != fred.darea) return false; if (dir != fred.dir) return false; return true; } bool CALCZONEELEMENT::operator <(FibHeapNode& RHS) { CALCZONEELEMENT& fred = (CALCZONEELEMENT&) RHS; float sw,dw; sw = GetWeight (sx,sy,dx,dy,sarea,darea); dw = GetWeight (fred.sx,fred.sy,fred.dx,fred.dy,fred.sarea,fred.darea); if (sw < dw) return true; if (dw < sw) return false; if (fred.sx < sx) return false; if (sx < fred.sx) return true; if (fred.dx < dx) return false; if (dx < fred.dx) return true; if (fred.sy < sy) return false; if (sy < fred.sy) return true; if (fred.dy < dy) return false; if (dy < fred.dy) return true; if (sarea < fred.sarea) return true; if (darea < fred.darea) return true; if (dir < fred.dir) return true; return true; } float GetOneCostZone (int sx,int sy,int offset,int areaentry,int areaexit,int newarea) { float toret; int dx,dy; dx = sx + offsetzone[offset][0]; dy = sy + offsetzone[offset][1]; if (dx<0) return -1.0; if (dy<0) return -1.0; if (dx>=MAPCELLCOUNT) return -1.0; if (dy>=MAPCELLCOUNT) return -1.0; if (areaentry == areaexit) { if (!g_MapCells[sx][sy].AreaData (areaentry).passable) return -1.0; toret = g_MapCells[sx][sy].AreaData (areaentry).weight; } else { if (!g_MapCells[sx][sy].AreaData (areaentry).passable) return -1.0; if (!g_MapCells[sx][sy].AreaData (areaexit).passable) return -1.0; toret = g_MapCells[sx][sy].AreaData (areaentry).weight/2.0 + g_MapCells[sx][sy].AreaData (areaexit).weight/2.0; } //TODO: add support for connection of areas within the zone #if 0 int x,y; bool flag; switch (offsetzone[offset][2]) { case 0: for (y=0;y>1)) : (t2+(t1>>1)); } CPoint GlobalToCellIndex (CPoint src) { int i; CPoint toret(-1,-1); for (i=0;i= g_MapCells[i][0].Left () && src.x <= g_MapCells[i][0].Right()) { toret.x = i; break; } } for (i=0;i= g_MapCells[0][i].Top () && src.y <= g_MapCells[0][i].Bottom()) { toret.y = i; break; } } return toret; } void FindLowerEdge (int dx,int dy,int endarea,int& sx,int& sy,int& curarea,int& dir,int startx,int starty,int startarea) { int i,j; float cost; float minvalue; minvalue = FLT_MAX; for (j=1;j=0) { for (y=0;y=0) { for (x=0;x *dest,CPoint gstart,CPoint gend) { int curarea,endarea,startarea; int i,j,k; FibHeap calc; CALCZONEELEMENT *temp; CPoint start,end; assert (gstart.x>=0); assert (gstart.x=0); assert (gstart.ypush (PATHZONEELEMENT (start.x,start.y,end.x,end.y,g_MapCells[start.x][start.y].AreaGlobal (gstart.x,gstart.y),g_MapCells[end.x][end.y].AreaGlobal (gend.x,gend.y),-1)); return true; } int x=-1,y=-1; bool done; while (!dest->empty ()) dest->pop (); for (i=0;idx == end.x) && (temp->dy == end.y) && (temp->darea == endarea)) done = true; else AddCalcElements (calc,temp->dx,temp->dy,temp->darea,GetWeight (temp->sx,temp->sy,temp->dx,temp->dy,temp->sarea,temp->darea)); delete temp; } while (temp = (CALCZONEELEMENT *) calc.ExtractMin ()) delete temp; if (!done) return false; done = false; int curx,cury; curx = end.x; cury = end.y; curarea = endarea; while (!done) { int dx,dy,darea,dir; FindLowerEdge (curx,cury,curarea,dx,dy,darea,dir,start.x,start.y,startarea); dest->push (PATHZONEELEMENT (dx,dy,curx,cury,darea,curarea,dir)); curx = dx; cury = dy; curarea = darea; if ((curx == start.x) && (cury == start.y) && (curarea == startarea)) { done = true; } } return true; }