initial commit, lordsawar source, slightly modified
[lordsawar] / src / Threatlist.cpp
1 // Copyright (C) 2004 John Farrell
2 // Copyright (C) 2004, 2005 Ulf Lorenz
3 // Copyright (C) 2005 Andrea Paternesi
4 // Copyright (C) 2007, 2009 Ben Asselstine
5 //
6 //  This program is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 3 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU Library General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
19 //  02110-1301, USA.
20
21 #include <iostream>
22 #include <algorithm>
23
24 #include "Threatlist.h"
25 #include "stack.h"
26 #include "ruin.h"
27 #include "player.h"
28 #include "AICityInfo.h"
29
30 using namespace std;
31
32 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl<<flush;}
33 #define debug(x)
34
35 Threatlist::Threatlist()
36 {
37 }
38
39 Threatlist::~Threatlist()
40 {
41 }
42
43 bool Threatlist::compareValue(const Threat *lhs, const Threat *rhs)  
44 {
45   return lhs->getValue() > rhs->getValue(); 
46 }
47 void Threatlist::sortByValue()
48 {
49   sort(compareValue);
50   /*
51   int count = 0;
52   for (Threatlist::iterator it = begin(); it != end(); it++)
53     {
54       if ((*it)->isCity())
55         {
56       printf ("%d. %f (%f)\n", count, (*it)->getValue(), (*it)->getStrength());
57               count++;
58                 }
59     }
60   */
61   /*
62     // bubble sort is the easiest thing I remember
63     bool sorted = false;
64
65     while (!sorted)
66     {
67         sorted = true;
68
69         // setup
70         iterator it = begin();
71         iterator nextit = it;
72         nextit++;
73
74         // now loop through the list
75         for (; nextit != end(); it++, nextit++)
76             if ((*it)->value() < (*nextit)->value())
77             {
78                 // exchange the two threats
79                 sorted = false;
80                 Threat* tmp = (*nextit);
81                 erase(nextit);
82                 nextit = it;
83
84                 it = insert(nextit, tmp);
85             }
86     }
87     */
88 }
89
90 void Threatlist::sortByDistance(Vector<int> pos)
91 {
92     // A simple bubble sort is propably too computationally expensive here.
93     // To reduce the overhead, we first calculate all distances, store them
94     // in another list and sort both lists together.
95
96     std::list<int> distances;
97
98     for (iterator it = begin(); it != end(); it++)
99     {
100         //int dist = abs((*it)->getClosestPoint(pos).x - pos.x);
101         //if (dist < abs((*it)->getClosestPoint(pos).y - pos.y))
102             //dist = abs((*it)->getClosestPoint(pos).y - pos.y);
103         distances.push_back(dist((*it)->getClosestPoint(pos), pos));
104     }
105
106     // now again a bubble sort :)
107     bool sorted = false;
108
109     while (!sorted)
110     {
111         sorted = true;
112
113         // setup
114         std::list<int>::iterator dit = distances.begin();
115         std::list<int>::iterator dnextit = distances.begin();
116         dnextit++;
117
118         iterator it = begin();
119         iterator nextit = it;
120         nextit++;
121
122         for (; nextit != end(); it++, nextit++, dit++, dnextit++)
123             if ((*dit) > (*dnextit))
124             {
125                 // exchange the items in both lists
126                 sorted = false;
127                 
128                 Threat* tmp = (*nextit);
129                 erase(nextit);
130                 nextit = it;
131                 it = insert(nextit, tmp);
132
133                 int val = (*dnextit);
134                 distances.erase(dnextit);
135                 dnextit = dit;
136                 dit = distances.insert(dnextit, val);
137             }
138     }
139 }
140
141 void Threatlist::addStack(Stack *stack)
142 {
143     for (iterator it = begin(); it != end(); it++)
144     {
145         Threat *threat = *it;
146         if (threat->Near(stack->getPos(), stack->getOwner()))
147         {
148             threat->addStack(stack);
149             return;
150         }
151     }
152
153     Threat *t = new Threat(stack);
154     push_back(t);
155 }
156
157 void Threatlist::addRuin(Ruin *ruin)
158 {
159     //if the ruin is abandoned, it is not a threat nor a valuable target
160     if (ruin->isSearched())
161         return;
162
163     Threat *t = new Threat(ruin);
164     push_back(t);
165 }
166
167 void Threatlist::findThreats(AICityInfo *info) const
168 {
169     //shortcut
170     Vector<int> location = info->getPos();
171
172     for (const_iterator it = begin(); it != end(); it++)
173     {
174         Threat *threat = *it;
175         Vector<int> closestPoint = threat->getClosestPoint(location);
176
177         //This happens only if a threat doesn't contain any stacks any longer.
178         if (closestPoint.x == -1)
179             continue;
180
181         int distToThreat = dist(closestPoint, location);
182
183         float movesToThreat = ((float) distToThreat + 6.0) / 7.0;
184         debug("moves to " << threat->toString() << " is " << movesToThreat)
185
186         //Ignore threats too far away
187         if (movesToThreat > 10.0)
188             continue;
189
190         if (movesToThreat <= 0.0)
191             movesToThreat = 1.0;
192
193         float strength = threat->getStrength();
194         if (strength == 0.0)
195             continue;
196
197         debug("strength of " << threat->toString() << " is " << strength)
198         float dangerFromThisThreat = strength / movesToThreat;
199         info->addThreat(dangerFromThisThreat, threat);
200
201         // a side-effect of this calculation is that we calculate the overall
202         // danger from each threat. If a threat threatens multiple cities, it
203         // is considered especially dangerous, so it is okay that we add the
204         // danger multiple times.
205         threat->addDanger(dangerFromThisThreat);
206     }
207 }
208
209 void Threatlist::deleteStack(guint32 id)
210 {
211     for (Threatlist::iterator it = begin(); it != end(); it++)
212         (*it)->deleteStack(id);
213 }
214
215 void Threatlist::deleteStack(Stack* s)
216 {
217     for (Threatlist::iterator it = begin(); it != end(); it++)
218         (*it)->deleteStack(s);
219 }
220
221 string Threatlist::toString() const
222 {
223     string result = "{";
224     bool first = true;
225     for (const_iterator it = begin(); it != end(); it++)
226     {
227         if (first)
228         {
229             first = false;
230         }
231         else
232         {
233             result += ",";
234         }
235         result = result + " " + (*it)->toString();
236     }
237     result += " }";
238     return result;
239 }
240
241 void Threatlist::flClear()
242 {
243     for (iterator it = begin(); it != end(); it++)
244         delete (*it);
245
246     clear();
247 }
248
249 Threatlist::iterator Threatlist::flErase(iterator object)
250 {
251     delete (*object);
252     return erase(object);
253 }
254
255 bool Threatlist::flRemove(Threat* object)
256 {
257     iterator threatit = find(begin(), end(), object);
258     if (threatit != end())
259     {
260         delete object;
261         erase(threatit);
262         return true;
263     }
264     return false;
265 }
266
267 void Threatlist::changeOwnership(Player *old_owner, Player *new_owner)
268 {
269   for (iterator it = begin(); it != end(); it++)
270     if ((*it)->getOwner() == old_owner)
271       (*it)->setOwner(new_owner);
272 }
273
274 // End of file