File: PathHeatMap.cpp

package info (click to toggle)
spring 106.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,316 kB
  • sloc: cpp: 543,954; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (111 lines) | stat: -rw-r--r-- 3,145 bytes parent folder | download | duplicates (3)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#include "PathHeatMap.hpp"
#include "PathConstants.h"
#include "PathManager.h"
#include "Sim/Misc/GlobalSynced.h"
#include "Sim/MoveTypes/MoveDefHandler.h"
#include "Sim/Objects/SolidObject.h"

// not extern'ed, so static
static PathHeatMap gPathHeatMap;


PathHeatMap* PathHeatMap::GetInstance() {
	gPathHeatMap.Init(PATH_HEATMAP_XSCALE, PATH_HEATMAP_ZSCALE);
	return &gPathHeatMap;
}

void PathHeatMap::FreeInstance(PathHeatMap* phm) {
	assert(phm == &gPathHeatMap);
	phm->Kill();
}



void PathHeatMap::Init(unsigned int scalex, unsigned int scalez) {
	xscale = std::max(1, std::min(mapDims.hmapx, int(scalex)));
	zscale = std::max(1, std::min(mapDims.hmapy, int(scalez)));
	xsize  = mapDims.hmapx / xscale;
	zsize  = mapDims.hmapy / zscale;

	heatMapOffset = 0;

	heatMap.resize(xsize * zsize);
}

unsigned int PathHeatMap::GetHeatMapIndex(unsigned int hmx, unsigned int hmz) const {
	assert(!heatMap.empty());

	// x & y are given in mapDims.mapi coords (:= mapDims.hmapi * 2)
	hmx >>= xscale;
	hmz >>= zscale;

	return (hmz * xsize + hmx);
}

void PathHeatMap::AddHeat(const CSolidObject* owner, const CPathManager* pm, unsigned int pathID) {
	if (pathID == 0)
		return;
	if (!owner->moveDef->heatMapping)
		return;

	// internally clears and reserves squares
	pm->GetDetailedPathSquares(pathID, pathSquares);

	if (pathSquares.empty())
		return;

	// called every frame by PathManager::UpdatePath
	//
	// the i-th waypoint receives an amount of heat equal to
	// ((N - i) / N) * heatProduced so the entire _remaining_
	// path is constantly reserved (the default PFS consumes
	// waypoints as they are passed by units) but far-future
	// waypoints do not contribute much cost for other units
	//
	//   i=0   --> value=((N-0)/N)*heatProd
	//   i=1   --> value=((N-1)/N)*heatProd
	//   ...
	//   i=N-1 --> value=((  1)/N)*heatProd
	//
	// NOTE:
	//   only the max-resolution pathfinder reacts to heat!
	//
	//   waypoints are spaced SQUARE_SIZE*2 elmos apart so
	//   the heatmapped paths look like "breadcrumb" trails
	//   this does not matter only because the default PFS
	//   uses the same spacing-factor between waypoints
	unsigned int i = pathSquares.size();

	const float scale = 1.0f / i;
	const float value = scale * owner->moveDef->heatProduced;

	for (const int2 sqr: pathSquares) {
		UpdateHeatValue(sqr.x, sqr.y, (i--) * value, owner->id);
	}
}

void PathHeatMap::UpdateHeatValue(unsigned int x, unsigned int y, unsigned int value, unsigned int ownerID) {
	const unsigned int idx = GetHeatMapIndex(x, y);

	if (heatMap[idx].value < (value + heatMapOffset)) {
		heatMap[idx].value = value + heatMapOffset;
		heatMap[idx].ownerID = ownerID;
	}
}

float PathHeatMap::GetHeatCost(unsigned int x, unsigned int z, const MoveDef& md, unsigned int ownerID) const {
	float c = 0.0f;

	if (!md.heatMapping)
		return c;

	const unsigned int idx = GetHeatMapIndex(x, z);
	const unsigned int val = (heatMapOffset >= heatMap[idx].value)? 0: (heatMap[idx].value - heatMapOffset);

	if (heatMap[idx].ownerID != ownerID)
		c = (md.heatMod * val);

	return c;
}