~ubuntu-branches/ubuntu/natty/spring/natty

« back to all changes in this revision

Viewing changes to AI/Skirmish/E323AI/ATask.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Ritchie
  • Date: 2010-09-23 18:56:03 UTC
  • mfrom: (3.1.9 experimental)
  • Revision ID: james.westby@ubuntu.com-20100923185603-st97s5chplo42y7w
Tags: 0.82.5.1+dfsg1-1ubuntu1
* Latest upstream version for online play
* debian/control: Replace (rather than conflict) spring-engine
  - spring-engine will be a dummy package (LP: #612905)
  - also set maintainer to MOTU

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "ATask.h"
 
2
 
 
3
#include "CGroup.h"
 
4
#include "CEconomy.h"
 
5
#include "CUnit.h"
 
6
 
 
7
int ATask::counter = 0;
 
8
 
 
9
ATask::ATask(AIClasses *_ai):ARegistrar(++counter, std::string("task")) {
 
10
        t = TASK_UNDEFINED;
 
11
        ai = _ai;
 
12
        active = false;
 
13
        suspended = false;
 
14
        isMoving = true;
 
15
        pos = ZEROVECTOR;
 
16
        initFrame = ai->cb->GetCurrentFrame();
 
17
        validateInterval = 5 * 30; // 5 sec by default
 
18
        nextValidateFrame = validateInterval;
 
19
        priority = 5;
 
20
        queueID = 0;
 
21
}
 
22
 
 
23
void ATask::remove() {
 
24
        LOG_II("ATask::remove " << (*this))
 
25
 
 
26
        // NOTE: removal order below is VERY important
 
27
 
 
28
        // remove current task from CTaskHandler, so it will mark this task 
 
29
        // to be killed on next update
 
30
        std::list<ARegistrar*>::iterator j = records.begin();
 
31
        while (j != records.end()) {
 
32
                ARegistrar *regobj = *j; ++j;
 
33
                regobj->remove(*this);
 
34
        }
 
35
 
 
36
        // remove all assisting tasks...
 
37
        std::list<ATask*>::iterator i = assisters.begin();
 
38
        while (i != assisters.end()) {
 
39
                ATask *task = *i; ++i;
 
40
                task->remove();
 
41
        }
 
42
        assert(assisters.size() == 0);
 
43
 
 
44
        // detach task from groups...
 
45
        std::list<CGroup*>::iterator itGroup = groups.begin();
 
46
        while(itGroup != groups.end()) {
 
47
                CGroup *g = *itGroup; ++itGroup;
 
48
                removeGroup(*g);
 
49
        }
 
50
 
 
51
        active = false;
 
52
}
 
53
 
 
54
// called on Group removing
 
55
void ATask::remove(ARegistrar &group) {
 
56
        CGroup *g = dynamic_cast<CGroup*>(&group);
 
57
        
 
58
        assert(g != NULL);
 
59
        
 
60
        removeGroup(*g);
 
61
        
 
62
        if (groups.empty()) {
 
63
                LOG_II("ATask::remove " << (*g))
 
64
 
 
65
                remove();
 
66
        }
 
67
}
 
68
 
 
69
CGroup* ATask::firstGroup() const {
 
70
        if (groups.empty())
 
71
                return NULL;
 
72
        return groups.front();
 
73
}
 
74
 
 
75
void ATask::addGroup(CGroup &g) {
 
76
        // FIXME: remove this when queue tasks will be supported
 
77
        assert(!g.busy);
 
78
        /*
 
79
        if (g->busy) {
 
80
                ATask *task = ai->tasks->getTask(g);
 
81
                assert(task != NULL && task != this);
 
82
                task->suspended = true;
 
83
                // TODO: nextTask = task;
 
84
        }
 
85
        */
 
86
        g.reg(*this);
 
87
        g.busy = true;
 
88
        g.micro(false);
 
89
        g.abilities(true);
 
90
        
 
91
        if (g.cats&STATIC)
 
92
                isMoving = false;
 
93
 
 
94
        groups.push_back(&g);
 
95
}
 
96
 
 
97
void ATask::removeGroup(CGroup &g) {
 
98
        g.unreg(*this);
 
99
        
 
100
        if (!suspended) {
 
101
                g.busy = false;
 
102
                g.unwait();
 
103
                g.micro(false);
 
104
                g.abilities(false);
 
105
                if (isMoving) g.stop();
 
106
        }
 
107
 
 
108
        groups.remove(&g);
 
109
}
 
110
 
 
111
bool ATask::enemyScan() {
 
112
        CGroup *group = firstGroup();
 
113
        bool scout = group->cats&SCOUTER;
 
114
        bool aircraft = group->cats&AIR;
 
115
        TargetsFilter tf;
 
116
 
 
117
        if (scout) {
 
118
                tf.threatCeiling = 1.1f;
 
119
                tf.threatRadius = 300.0f;
 
120
        }
 
121
        else {
 
122
                if (aircraft) {
 
123
                        if (group->cats&ASSAULT)
 
124
                                tf.threatCeiling = group->strength;
 
125
                        else
 
126
                                tf.threatCeiling = 1.1f;
 
127
                        // TODO: replace with maneuvering radius?
 
128
                        tf.threatRadius = 300.0f;
 
129
                }
 
130
                else {
 
131
                        tf.exclude = SCOUTER;
 
132
                        tf.threatFactor = 0.001f;
 
133
                        tf.threatCeiling = group->strength;
 
134
                        tf.threatRadius = 0.0f;
 
135
                }
 
136
        }
 
137
 
 
138
        // do not chase after aircraft by non-aircraft groups...
 
139
        if (!aircraft)
 
140
                tf.exclude |= AIR;
 
141
 
 
142
        int target = group->selectTarget(group->getScanRange(), tf);
 
143
 
 
144
        if (target >= 0) {
 
145
                group->attack(target);
 
146
                group->micro(true);
 
147
                if (scout)
 
148
                        LOG_II("ATask::enemyScan scout " << (*group) << " is microing enemy target Unit(" << target << ")")
 
149
                else
 
150
                        LOG_II("ATask::enemyScan engage " << (*group) << " is microing enemy target Unit(" << target << ")")
 
151
                return true;
 
152
        }
 
153
 
 
154
        return false;
 
155
}
 
156
 
 
157
bool ATask::resourceScan() {
 
158
        bool isFeature = true;
 
159
        int bestFeature = -1;
 
160
        float bestDist = std::numeric_limits<float>::max();
 
161
        CGroup *group = firstGroup();
 
162
        // NOTE: do not use group->los because it is too small and do not 
 
163
        // correspond to real map units
 
164
        float radius = group->buildRange;
 
165
        float3 gpos = group->pos();
 
166
 
 
167
        assert(radius > EPS);
 
168
 
 
169
        // reclaim features when we can store metal only...
 
170
        if (!ai->economy->mexceeding) {
 
171
                const int numFeatures = ai->cb->GetFeatures(&ai->unitIDs[0], MAX_FEATURES, gpos, 1.5f * radius);
 
172
                for (int i = 0; i < numFeatures; i++) {
 
173
                        const int uid = ai->unitIDs[i];
 
174
                        const FeatureDef *fd = ai->cb->GetFeatureDef(uid);
 
175
                        if (fd->metal > 0.0f) {
 
176
                                float3 fpos = ai->cb->GetFeaturePos(uid);
 
177
                                float dist = gpos.distance2D(fpos);
 
178
                                if (dist < bestDist) {
 
179
                                        bestFeature = uid;
 
180
                                        bestDist = dist;
 
181
                                }
 
182
                        }
 
183
                }
 
184
        }
 
185
 
 
186
        // if there is no feature available then reclaim enemy unarmed building, 
 
187
        // hehe :)
 
188
        if (bestFeature == -1) {
 
189
                std::map<int, bool> occupied;
 
190
                TargetsFilter tf;
 
191
                tf.include = STATIC;
 
192
                tf.exclude = ATTACKER;
 
193
                tf.threatCeiling = 1.1f;
 
194
                tf.threatRadius = radius;
 
195
                
 
196
                bestFeature = group->selectTarget(radius, tf);
 
197
                
 
198
                isFeature = false;
 
199
        }                       
 
200
        
 
201
        if (bestFeature != -1) {
 
202
                group->reclaim(bestFeature, isFeature);
 
203
                group->micro(true);
 
204
                LOG_II("ATask::resourceScan group " << (*group) << " is reclaiming")
 
205
                return true;
 
206
        }
 
207
 
 
208
        return false;
 
209
}
 
210
 
 
211
bool ATask::repairScan() {
 
212
        if (ai->economy->mstall || ai->economy->estall)
 
213
                return false;
 
214
        
 
215
        int bestUnit = -1;
 
216
        float bestScore = 0.0f;
 
217
        CGroup *group = firstGroup();
 
218
        float radius = group->buildRange;
 
219
        float3 gpos = group->pos();
 
220
 
 
221
        const int numUnits = ai->cb->GetFriendlyUnits(&ai->unitIDs[0], gpos, 2.0f * radius, MAX_FEATURES);
 
222
        for (int i = 0; i < numUnits; i++) {
 
223
                const int uid = ai->unitIDs[i];
 
224
                
 
225
                if (ai->cb->UnitBeingBuilt(uid) || group->firstUnit()->key == uid)
 
226
                        continue;
 
227
                
 
228
                const float healthDamage = ai->cb->GetUnitMaxHealth(uid) - ai->cb->GetUnitHealth(uid);
 
229
                if (healthDamage > EPS) {
 
230
                        // TODO: somehow limit number of repairing builders per unit
 
231
                        const UnitDef *ud = ai->cb->GetUnitDef(uid);
 
232
                        const float score = healthDamage + (CUnit::isDefense(ud) ? 10000.0f: 0.0f) + (CUnit::isStatic(ud) ? 5000.0f: 0.0f);
 
233
                        if (score > bestScore) {
 
234
                                bestUnit = uid;
 
235
                                bestScore = score;
 
236
                        }
 
237
                }
 
238
        }
 
239
 
 
240
        if (bestUnit != -1) {
 
241
                group->repair(bestUnit);
 
242
                group->micro(true);
 
243
                LOG_II("ATask::repairScan group " << (*group) << " is repairing")
 
244
                return true;
 
245
        }
 
246
 
 
247
        return false;
 
248
}
 
249
 
 
250
int ATask::lifeFrames() const {
 
251
        return ai->cb->GetCurrentFrame() - initFrame;
 
252
}
 
253
 
 
254
float ATask::lifeTime() const {
 
255
        return (float)(ai->cb->GetCurrentFrame() - initFrame) / 30.0f;
 
256
}
 
257
 
 
258
void ATask::update() {
 
259
        if (!active) return;
 
260
 
 
261
        if (validateInterval > 0) {
 
262
                int lifetime = lifeFrames();
 
263
                if (lifetime >= nextValidateFrame) {
 
264
                        if (!onValidate()) {
 
265
                                remove();
 
266
                                return;
 
267
                        }
 
268
                        else
 
269
                                nextValidateFrame = lifetime + validateInterval;
 
270
                }
 
271
        }
 
272
 
 
273
        if (suspended) return;
 
274
 
 
275
        onUpdate();
 
276
}
 
277
 
 
278
std::ostream& operator<<(std::ostream &out, const ATask &atask) {
 
279
        atask.toStream(out);
 
280
 
 
281
        if (atask.assisters.size() > 0) {
 
282
                out << " Assisters: amount(" << atask.assisters.size() << ") [";
 
283
                std::list<ATask*>::const_iterator i;
 
284
                for (i = atask.assisters.begin(); i != atask.assisters.end(); ++i) {
 
285
                        CGroup *group = (*i)->firstGroup();
 
286
                        if (group)
 
287
                                out << (*group);
 
288
                }
 
289
                out << "]";
 
290
        }
 
291
        
 
292
        return out;
 
293
}