File: PathHeatMap.cpp

package info (click to toggle)
spring 98.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 41,928 kB
  • ctags: 60,665
  • sloc: cpp: 356,167; ansic: 39,434; python: 12,228; java: 12,203; awk: 5,856; sh: 1,719; xml: 997; perl: 405; php: 253; objc: 194; makefile: 72; sed: 2
file content (115 lines) | stat: -rw-r--r-- 3,248 bytes parent folder | download
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
112
113
114
115
/* 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"

PathHeatMap* PathHeatMap::GetInstance() {
	static PathHeatMap* phm = NULL;

	if (phm == NULL) {
		phm = new PathHeatMap(PATH_HEATMAP_XSCALE, PATH_HEATMAP_ZSCALE);
	}

	return phm;
}

void PathHeatMap::FreeInstance(PathHeatMap* phm) {
	delete phm;
}



PathHeatMap::PathHeatMap(unsigned int scalex, unsigned int scalez): enabled(true) {
	xscale = std::max(1, std::min(gs->hmapx, int(scalex)));
	zscale = std::max(1, std::min(gs->hmapy, int(scalez)));
	xsize  = gs->hmapx / xscale;
	zsize  = gs->hmapy / zscale;

	heatMap.resize(xsize * zsize, HeatCell());
	heatMapOffset = 0;
}

PathHeatMap::~PathHeatMap() {
	heatMap.clear();
}

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

	//! x & y are given in gs->mapi coords (:= gs->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;

	std::vector<int2> points;

	pm->GetDetailedPathSquares(pathID, points);

	if (!points.empty()) {
		// 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
		const float scale = 1.0f / points.size();
		const float value = scale * owner->moveDef->heatProduced;

		unsigned int i = points.size();

		for (std::vector<int2>::const_iterator it = points.begin(); it != points.end(); ++it) {
			UpdateHeatValue(it->x, it->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 (!enabled) { return c; }
	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;
}