File: CThreatMap.cpp

package info (click to toggle)
spring 0.81.2.1%2Bdfsg1-6
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 28,496 kB
  • ctags: 37,096
  • sloc: cpp: 238,659; ansic: 13,784; java: 12,175; awk: 3,428; python: 1,159; xml: 738; perl: 405; sh: 297; makefile: 267; pascal: 228; objc: 192
file content (160 lines) | stat: -rw-r--r-- 4,439 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "CThreatMap.h"

#include <math.h>
#include <map>

#include "CAI.h"
#include "CUnitTable.h"
#include "CUnit.h"
#include "MathUtil.h"

CThreatMap::CThreatMap(AIClasses *ai) {
	this->ai = ai;
	this->X  = ai->cb->GetMapWidth() / (HEIGHT2SLOPE*I_MAP_RES);
	this->Z  = ai->cb->GetMapHeight() / (HEIGHT2SLOPE*I_MAP_RES);
	REAL     = HEIGHT2SLOPE*HEIGHT2REAL*I_MAP_RES;
	map      = new float[X*Z];
	
	units = &ai->unitIDs[0]; // save about 4x32KB of memory

	for (int i = 0; i < X*Z; i++)
		map[i] = 1.0f;
}

CThreatMap::~CThreatMap() {
	delete[] map;
}

float CThreatMap::getThreat(float3 &center, float radius) {
	int i = center.z / REAL;
	int j = center.x / REAL;
	if (radius == 0.0f)
		return map[ID(j,i)];
	int R = ceil(radius / REAL);
	float power = 0.0f;
	for (int z = -R; z <= R; z++) {
		int zz = z+i;
		if (zz > Z-1 || zz < 0)
			continue;
		for (int x = -R; x <= R; x++) {
			int xx = x+j;
			if (xx < X-1 && xx >= 0)
				power += map[ID(xx,zz)];
		}
	}
	return power/(2.0f*R*M_PI);
}

void CThreatMap::update(int frame) {
	totalPower = 0.0f;
	for (int i = 0; i < X*Z; i++)
		map[i] = 1.0f;

	int numUnits = ai->cbc->GetEnemyUnits(units, MAX_UNITS_AI);
	if (numUnits > MAX_UNITS_AI)
		LOG_WW("CThreatMap::update " << numUnits << " > " << MAX_UNITS_AI)

	/* Add enemy threats */
	for (int i = 0; i < numUnits; i++) {
		const UnitDef  *ud = ai->cbc->GetUnitDef(units[i]);
		const UnitType *ut = UT(ud->id);
		
		/* Don't let air be part of the threatmap */
		if ((ut->cats&ATTACKER) && (ut->cats&AIR) && (ut->cats&MOBILE))
			continue;

		/* Ignore paralyzed units */
		if (ai->cbc->IsUnitParalyzed(units[i]))
			continue;

		if ((ut->cats&ATTACKER) && !(ut->cats&AIR) && !ai->cbc->UnitBeingBuilt(units[i])) {
			const float3  upos = ai->cbc->GetUnitPos(units[i]);
			const float uRealX = upos.x/REAL;
			const float uRealZ = upos.z/REAL;
			const float range = (ud->maxWeaponRange+100.0f)/REAL;
			float       powerT = ai->cbc->GetUnitPower(units[i]);
			const float power = ut->cats&COMMANDER ? powerT/20.0f : powerT;
			float3 pos(0.0f, 0.0f, 0.0f);

			const int R = (int) ceil(range);
			for (int z = -R; z <= R; z++) {
				for (int x = -R; x <= R; x++) {
					pos.x = x;
					pos.z = z;
					if (pos.Length2D() <= range) {
						pos.x += uRealX;
						pos.z += uRealZ;
						const unsigned int mx = (unsigned int) round(pos.x);
						const unsigned int mz = (unsigned int) round(pos.z);
						if (mx < X && mz < Z)
							map[ID(mx,mz)] += power;
					}
				}
			}
			totalPower += power;
		}
	}

	/* Add friendlies, this encourages flanking */
//	std::map<int, CUnit*>::iterator i;
//	for (i = ai->unittable->activeUnits.begin(); i != ai->unittable->activeUnits.end(); i++) {
//		const UnitDef  *ud = i->second->def;
//		const UnitType *ut = i->second->type;
//		
//		/* Don't let air be part of the threatmap */
//		if ((ut->cats&ATTACKER) && (ut->cats&AIR) && (ut->cats&MOBILE))
//			continue;
//
//		/* Ignore paralyzed units */
//		if (ai->cbc->IsUnitParalyzed(i->first))
//			continue;
//
//		if ((ut->cats&ATTACKER)) {
//			const float3  upos = i->second->pos();
//			const float uRealX = upos.x/REAL;
//			const float uRealZ = upos.z/REAL;
//			const float range = (ud->maxWeaponRange+100.0f)/REAL;
//			float       powerT = ud->power;
//			const float power = 0.1f * (ut->cats&COMMANDER ? powerT/20.0f : powerT);
//			float3 pos(0.0f, 0.0f, 0.0f);
//
//			const int R = (int) ceil(range);
//			for (int z = -R; z <= R; z++) {
//				for (int x = -R; x <= R; x++) {
//					pos.x = x;
//					pos.z = z;
//					if (pos.Length2D() <= range) {
//						pos.x += uRealX;
//						pos.z += uRealZ;
//						const unsigned int mx = (unsigned int) round(pos.x);
//						const unsigned int mz = (unsigned int) round(pos.z);
//						if (mx < X && mz < Z)
//							map[ID(mx,mz)] += power;
//					}
//				}
//			}
//			totalPower += power;
//		}
//	}
//	draw();
}

float CThreatMap::gauss(float x, float sigma, float mu) {
	float a = 1.0f / (sigma * sqrt(2*M_PI));
	float b = exp( -( pow(x-mu, 2) / (2*(pow(sigma,2))) ) );
	return a * b;
}

void CThreatMap::draw() {
	for (int z = 0; z < Z; z++) {
		for (int x = 0; x < X; x++) {
			if (map[ID(x,z)] > 1.0f+EPSILON) {
				float3 p0(x*REAL, ai->cb->GetElevation(x*REAL,z*REAL), z*REAL);
				float3 p1(p0);
				p1.y += (map[ID(x,z)]/totalPower) * 300.0f;
				ai->cb->CreateLineFigure(p0, p1, 4, 10.0, DRAW_TIME, 5);
			}
		}
	}
	ai->cb->SetFigureColor(5, 1.0f, 0.0f, 0.0f, 1.0f);
}