forked from davechurchill/commandcenter
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDistanceMap.cpp
More file actions
92 lines (75 loc) · 2.72 KB
/
DistanceMap.cpp
File metadata and controls
92 lines (75 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "DistanceMap.h"
#include "CCBot.h"
#include "Util.h"
const size_t LegalActions = 4;
const int actionX[LegalActions] = {1, -1, 0, 0};
const int actionY[LegalActions] = {0, 0, 1, -1};
DistanceMap::DistanceMap()
{
}
int DistanceMap::getDistance(int tileX, int tileY) const
{
BOT_ASSERT(tileX < m_width && tileY < m_height, "Index out of range: X = %d, Y = %d", tileX, tileY);
return m_dist[tileX][tileY];
}
int DistanceMap::getDistance(const CCTilePosition & pos) const
{
return getDistance(pos.x, pos.y);
}
int DistanceMap::getDistance(const CCPosition & pos) const
{
return getDistance(CCTilePosition((int)pos.x, (int)pos.y));
}
const std::vector<CCTilePosition> & DistanceMap::getSortedTiles() const
{
return m_sortedTiles;
}
// Computes m_dist[x][y] = ground distance from (startX, startY) to (x,y)
// Uses BFS, since the map is quite large and DFS may cause a stack overflow
void DistanceMap::computeDistanceMap(CCBot & m_bot, const CCTilePosition & startTile)
{
m_startTile = startTile;
m_width = m_bot.Map().width();
m_height = m_bot.Map().height();
m_dist = std::vector<std::vector<int>>(m_width, std::vector<int>(m_height, -1));
m_sortedTiles.reserve(m_width * m_height);
// the fringe for the BFS we will perform to calculate distances
std::vector<CCTilePosition> fringe;
fringe.reserve(m_width * m_height);
fringe.push_back(startTile);
m_sortedTiles.push_back(startTile);
m_dist[(int)startTile.x][(int)startTile.y] = 0;
for (size_t fringeIndex=0; fringeIndex<fringe.size(); ++fringeIndex)
{
auto & tile = fringe[fringeIndex];
// check every possible child of this tile
for (size_t a=0; a<LegalActions; ++a)
{
CCTilePosition nextTile(tile.x + actionX[a], tile.y + actionY[a]);
// if the new tile is inside the map bounds, is walkable, and has not been visited yet, set the distance of its parent + 1
if (m_bot.Map().isWalkable(nextTile) && getDistance(nextTile) == -1)
{
m_dist[(int)nextTile.x][(int)nextTile.y] = m_dist[(int)tile.x][(int)tile.y] + 1;
fringe.push_back(nextTile);
m_sortedTiles.push_back(nextTile);
}
}
}
}
void DistanceMap::draw(CCBot & bot) const
{
const int tilesToDraw = 200;
for (size_t i(0); i < tilesToDraw; ++i)
{
auto & tile = m_sortedTiles[i];
int dist = getDistance(tile);
CCPosition textPos(tile.x + Util::TileToPosition(0.5), tile.y + Util::TileToPosition(0.5));
std::stringstream ss;
ss << dist;
bot.Map().drawText(textPos, ss.str());
}
}
const CCTilePosition & DistanceMap::getStartTile() const
{
return m_startTile;
}