-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathai.cpp
More file actions
104 lines (91 loc) · 2.88 KB
/
ai.cpp
File metadata and controls
104 lines (91 loc) · 2.88 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
93
94
95
96
97
98
99
100
101
102
103
104
#include "ai.hpp"
namespace TerraNova {
void TacticalAI::AddUnit(std::shared_ptr<Unit> newUnit){
if(!newUnit){
std::cerr << "Warning: attempted to add a nullptr Unit to a TacticalAI."
<< std::endl;
return;
}
if(newUnit->Faction() == faction){
myUnits.push_back(newUnit);
} else {
enemyUnits.push_back(newUnit);
}
}
void TacticalAI::StartTurn(){
myUnits.StartTurn();
enemyUnits.StartTurn();
}
void TacticalAI::EndTurn(){
myUnits.EndTurn();
enemyUnits.EndTurn();
}
void TacticalAI::GiveOrders(){
/*std::cout << "Giving orders to " << myUnits.size() << " units to attack "
<< enemyUnits.size() << " enemies." << std::endl;
std::cout << "My units:" << std::endl;
for(auto& buddy : myUnits) std::cout << buddy->Spec()->Name() << std::endl;
std::cout << "Enemy units:" << std::endl;
for(auto& jerk : enemyUnits) std::cout << jerk->Spec()->Name() << std::endl;*/
for(auto& chump : myUnits){
if(enemyUnits.size() == 0 || !chump->CanAttack()){
chump->OrderPatrol();
continue;
}
Unit* target = FindNearestEnemy(*chump);
if(target){
chump->OrderMove(map.PathTo(
chump->Location(), target->Location(), chump->MoveCosts()));
} else {
chump->OrderPatrol();
}
}
}
Unit* TacticalAI::FindNearestEnemy(const Unit& attacker){
if(enemyUnits.size() == 0){
std::cerr << "Warning: TacticalAI asked to find nearest enemy, but no "
<< "enemies were known." << std::endl;
return nullptr;
}
unsigned int bestPriority = -1u;
Unit* closestEnemy = nullptr;
unsigned int currentDistance, currentPriority;
for(auto i = 0u; i < enemyUnits.size(); ++i){
currentDistance = map.DistanceBetween(attacker.Location(),
enemyUnits[i]->Location(), attacker.MoveCosts());
// -----------------------------
// the following line is temporary -- a TacticalAI should always be
// willing to engage with any enemy it knows about. Instead we should
// just not be handing far-off enemies to the TacticalAI.
if(currentDistance > 3) continue;
// -----------------------------
currentPriority = TargetPriority(*enemyUnits[i], currentDistance);
if(currentPriority < bestPriority
|| ((currentPriority == bestPriority) && Random::Bool())){
closestEnemy = enemyUnits[i];
bestPriority = currentPriority;
}
}
return closestEnemy;
}
unsigned int TacticalAI::TargetPriority(const Unit& target,
const unsigned int distance) const{
return 1000*distance + (100*target.Health())/target.MaxHealth();
}
AIPlayer::AIPlayer(Map& map, const int faction): map(map), faction(faction){
tacticalAIs.emplace_back(map, faction);
}
// temporary placeholder
void AIPlayer::AddUnit(std::shared_ptr<Unit> newUnit){
tacticalAIs[0].AddUnit(newUnit);
}
void AIPlayer::StartTurn(){
for(auto& tai : tacticalAIs) tai.StartTurn();
}
void AIPlayer::EndTurn(){
for(auto& tai : tacticalAIs) tai.EndTurn();
}
void AIPlayer::GiveOrders(){
for(auto& tai : tacticalAIs) tai.GiveOrders();
}
} // namespace TerraNova