1 #include "CTaskHandler.h"
2
3 #include <iostream>
4 #include <sstream>
5 #include <string>
6 #include <math.h>
7 #include <limits>
8
9 #include "CUnitTable.h"
10 #include "CPathfinder.h"
11 #include "CUnit.h"
12 #include "CGroup.h"
13 #include "CEconomy.h"
14 #include "CConfigParser.h"
15 #include "CThreatMap.h"
16 #include "CScopedTimer.h"
17 #include "CDefenseMatrix.h"
18
19
CTaskHandler(AIClasses * ai)20 CTaskHandler::CTaskHandler(AIClasses *ai): ARegistrar(500) {
21 this->ai = ai;
22
23 statsMaxActiveTasks = 0;
24 statsMaxTasks = 0;
25 }
26
~CTaskHandler()27 CTaskHandler::~CTaskHandler() {
28 //LOG_II("CTaskHandler::Stats MaxActiveTasks = " << statsMaxActiveTasks)
29 LOG_II("CTaskHandler::Stats MaxTasks = " << statsMaxTasks)
30
31 std::list<ATask*>::iterator it;
32 for (it = processQueue.begin(); it != processQueue.end(); ++it)
33 delete *it;
34 }
35
remove(ARegistrar & obj)36 void CTaskHandler::remove(ARegistrar &obj) {
37 switch(obj.regtype()) {
38 case ARegistrar::TASK: {
39 ATask *task = dynamic_cast<ATask*>(&obj);
40 LOG_II("CTaskHandler::remove " << (*task))
41 for(std::list<CGroup*>::iterator it = task->groups.begin(); it != task->groups.end(); ++it) {
42 CGroup *group = *it;
43 group->unreg(*this);
44 groupToTask.erase(group->key);
45 if (task->isMoving)
46 ai->pathfinder->remove(*group);
47 }
48 activeTasks[task->t].erase(task->key);
49 obsoleteTasks.push(task);
50 break;
51 }
52 case ARegistrar::GROUP: {
53 CGroup *group = dynamic_cast<CGroup*>(&obj);
54 LOG_II("CTaskHandler::remove " << (*group))
55 groupToTask.erase(group->key);
56 break;
57 }
58 default:
59 assert(false);
60 }
61
62 obj.unreg(*this);
63 }
64
update()65 void CTaskHandler::update() {
66 /* delete obsolete tasks from memory */
67 while(!obsoleteTasks.empty()) {
68 ATask *task = obsoleteTasks.top();
69 processQueue.remove(task);
70 obsoleteTasks.pop();
71 // make sure task is really detached from groups
72 assert(task->groups.size() == 0);
73 delete task;
74 }
75
76 /* Begin task updates */
77 if (!processQueue.empty()) {
78 ATask *task;
79
80 if (processQueue.size() == 1) {
81 task = processQueue.front();
82 if (task->active) task->update();
83 }
84 else {
85 int c = 0; // active tasks counter
86 std::list<ATask*>::iterator it = processQueue.begin();
87 ATask *taskFirst = *it;
88
89 do {
90 task = *it;
91
92 if (task->active) {
93 task->update();
94 c++;
95 }
96
97 ++it;
98
99 // imitate circle queue...
100 processQueue.pop_front();
101 processQueue.push_back(task);
102
103 assert(it != processQueue.end());
104 } while (c < MAX_TASKS_PER_UPDATE && (*it)->key != taskFirst->key);
105 }
106
107 statsMaxTasks = std::max<int>(statsMaxTasks, processQueue.size());
108 }
109 }
110
getPos(const CGroup & group)111 float3 CTaskHandler::getPos(const CGroup& group) {
112 assert(groupToTask.find(group.key) != groupToTask.end());
113 return groupToTask[group.key]->pos;
114 }
115
getTask(const CGroup & group)116 ATask* CTaskHandler::getTask(const CGroup& group) {
117 std::map<int, ATask*>::iterator i = groupToTask.find(group.key);
118 if (i == groupToTask.end())
119 return NULL;
120 return i->second;
121 }
122
getTaskByTarget(int uid)123 ATask* CTaskHandler::getTaskByTarget(int uid) {
124 std::map<int, ATask*>::iterator i;
125 for (i = activeTasks[TASK_ATTACK].begin(); i != activeTasks[TASK_ATTACK].end(); ++i) {
126 if (((AttackTask*)i->second)->target == uid)
127 return i->second;
128 }
129 return NULL;
130 }
131
addTask(ATask * task,ATask::NPriority p)132 bool CTaskHandler::addTask(ATask* task, ATask::NPriority p) {
133 if (task == NULL)
134 return false;
135
136 assert(task->t != TASK_UNDEFINED);
137
138 task->priority = p;
139
140 std::list<CGroup*>::iterator it;
141
142 // NOTE: this is required because otherwise memory used by task will never
143 // be freed
144 task->reg(*this);
145 processQueue.push_back(task);
146 // NOTE: this is required because within ATask::onValidate() a path
147 // (or even paths) can be added, which in its turn calls
148 // CTaskHandler::getPos()
149 for (it = task->groups.begin(); it != task->groups.end(); ++it) {
150 (*it)->reg(*this);
151 groupToTask[(*it)->key] = task;
152 }
153
154 LOG_II((*task))
155
156 if (!task->onValidate()) {
157 task->remove();
158 return false;
159 }
160
161 // TODO: after MoveTask is implemented remove the code below
162 for(it = task->groups.begin(); it != task->groups.end(); ++it) {
163 CGroup* group = *it;
164 if (task->isMoving && !ai->pathfinder->pathAssigned(*group)) {
165 if(!ai->pathfinder->addGroup(*group)) {
166 task->remove();
167 return false;
168 }
169 }
170 }
171
172 activeTasks[task->t][task->key] = task;
173
174 task->active = true;
175
176 return true;
177 }
178
onEnemyDestroyed(int enemy,int attacker)179 void CTaskHandler::onEnemyDestroyed(int enemy, int attacker) {
180 std::list<ATask*>::iterator it = processQueue.begin();
181 ATask *task;
182 while (it != processQueue.end()) {
183 task = *it; ++it;
184 if (task->active)
185 task->onEnemyDestroyed(enemy, attacker);
186 }
187 }
188
onUnitDestroyed(int uid,int attacker)189 void CTaskHandler::onUnitDestroyed(int uid, int attacker) {
190 std::list<ATask*>::iterator it = processQueue.begin();
191 ATask *task;
192 while (it != processQueue.end()) {
193 task = *it; ++it;
194 if (task->active)
195 task->onUnitDestroyed(uid, attacker);
196 }
197 }
198