--- /dev/null
+// Copyright (C) 2004 John Farrell
+// Copyright (C) 2004, 2005 Ulf Lorenz
+// Copyright (C) 2005 Andrea Paternesi
+// Copyright (C) 2007, 2009 Ben Asselstine
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301, USA.
+
+#include <iostream>
+#include <algorithm>
+
+#include "Threatlist.h"
+#include "stack.h"
+#include "ruin.h"
+#include "player.h"
+#include "AICityInfo.h"
+
+using namespace std;
+
+//#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl<<flush;}
+#define debug(x)
+
+Threatlist::Threatlist()
+{
+}
+
+Threatlist::~Threatlist()
+{
+}
+
+bool Threatlist::compareValue(const Threat *lhs, const Threat *rhs)
+{
+ return lhs->getValue() > rhs->getValue();
+}
+void Threatlist::sortByValue()
+{
+ sort(compareValue);
+ /*
+ int count = 0;
+ for (Threatlist::iterator it = begin(); it != end(); it++)
+ {
+ if ((*it)->isCity())
+ {
+ printf ("%d. %f (%f)\n", count, (*it)->getValue(), (*it)->getStrength());
+ count++;
+ }
+ }
+ */
+ /*
+ // bubble sort is the easiest thing I remember
+ bool sorted = false;
+
+ while (!sorted)
+ {
+ sorted = true;
+
+ // setup
+ iterator it = begin();
+ iterator nextit = it;
+ nextit++;
+
+ // now loop through the list
+ for (; nextit != end(); it++, nextit++)
+ if ((*it)->value() < (*nextit)->value())
+ {
+ // exchange the two threats
+ sorted = false;
+ Threat* tmp = (*nextit);
+ erase(nextit);
+ nextit = it;
+
+ it = insert(nextit, tmp);
+ }
+ }
+ */
+}
+
+void Threatlist::sortByDistance(Vector<int> pos)
+{
+ // A simple bubble sort is propably too computationally expensive here.
+ // To reduce the overhead, we first calculate all distances, store them
+ // in another list and sort both lists together.
+
+ std::list<int> distances;
+
+ for (iterator it = begin(); it != end(); it++)
+ {
+ //int dist = abs((*it)->getClosestPoint(pos).x - pos.x);
+ //if (dist < abs((*it)->getClosestPoint(pos).y - pos.y))
+ //dist = abs((*it)->getClosestPoint(pos).y - pos.y);
+ distances.push_back(dist((*it)->getClosestPoint(pos), pos));
+ }
+
+ // now again a bubble sort :)
+ bool sorted = false;
+
+ while (!sorted)
+ {
+ sorted = true;
+
+ // setup
+ std::list<int>::iterator dit = distances.begin();
+ std::list<int>::iterator dnextit = distances.begin();
+ dnextit++;
+
+ iterator it = begin();
+ iterator nextit = it;
+ nextit++;
+
+ for (; nextit != end(); it++, nextit++, dit++, dnextit++)
+ if ((*dit) > (*dnextit))
+ {
+ // exchange the items in both lists
+ sorted = false;
+
+ Threat* tmp = (*nextit);
+ erase(nextit);
+ nextit = it;
+ it = insert(nextit, tmp);
+
+ int val = (*dnextit);
+ distances.erase(dnextit);
+ dnextit = dit;
+ dit = distances.insert(dnextit, val);
+ }
+ }
+}
+
+void Threatlist::addStack(Stack *stack)
+{
+ for (iterator it = begin(); it != end(); it++)
+ {
+ Threat *threat = *it;
+ if (threat->Near(stack->getPos(), stack->getOwner()))
+ {
+ threat->addStack(stack);
+ return;
+ }
+ }
+
+ Threat *t = new Threat(stack);
+ push_back(t);
+}
+
+void Threatlist::addRuin(Ruin *ruin)
+{
+ //if the ruin is abandoned, it is not a threat nor a valuable target
+ if (ruin->isSearched())
+ return;
+
+ Threat *t = new Threat(ruin);
+ push_back(t);
+}
+
+void Threatlist::findThreats(AICityInfo *info) const
+{
+ //shortcut
+ Vector<int> location = info->getPos();
+
+ for (const_iterator it = begin(); it != end(); it++)
+ {
+ Threat *threat = *it;
+ Vector<int> closestPoint = threat->getClosestPoint(location);
+
+ //This happens only if a threat doesn't contain any stacks any longer.
+ if (closestPoint.x == -1)
+ continue;
+
+ int distToThreat = dist(closestPoint, location);
+
+ float movesToThreat = ((float) distToThreat + 6.0) / 7.0;
+ debug("moves to " << threat->toString() << " is " << movesToThreat)
+
+ //Ignore threats too far away
+ if (movesToThreat > 10.0)
+ continue;
+
+ if (movesToThreat <= 0.0)
+ movesToThreat = 1.0;
+
+ float strength = threat->getStrength();
+ if (strength == 0.0)
+ continue;
+
+ debug("strength of " << threat->toString() << " is " << strength)
+ float dangerFromThisThreat = strength / movesToThreat;
+ info->addThreat(dangerFromThisThreat, threat);
+
+ // a side-effect of this calculation is that we calculate the overall
+ // danger from each threat. If a threat threatens multiple cities, it
+ // is considered especially dangerous, so it is okay that we add the
+ // danger multiple times.
+ threat->addDanger(dangerFromThisThreat);
+ }
+}
+
+void Threatlist::deleteStack(guint32 id)
+{
+ for (Threatlist::iterator it = begin(); it != end(); it++)
+ (*it)->deleteStack(id);
+}
+
+void Threatlist::deleteStack(Stack* s)
+{
+ for (Threatlist::iterator it = begin(); it != end(); it++)
+ (*it)->deleteStack(s);
+}
+
+string Threatlist::toString() const
+{
+ string result = "{";
+ bool first = true;
+ for (const_iterator it = begin(); it != end(); it++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ result += ",";
+ }
+ result = result + " " + (*it)->toString();
+ }
+ result += " }";
+ return result;
+}
+
+void Threatlist::flClear()
+{
+ for (iterator it = begin(); it != end(); it++)
+ delete (*it);
+
+ clear();
+}
+
+Threatlist::iterator Threatlist::flErase(iterator object)
+{
+ delete (*object);
+ return erase(object);
+}
+
+bool Threatlist::flRemove(Threat* object)
+{
+ iterator threatit = find(begin(), end(), object);
+ if (threatit != end())
+ {
+ delete object;
+ erase(threatit);
+ return true;
+ }
+ return false;
+}
+
+void Threatlist::changeOwnership(Player *old_owner, Player *new_owner)
+{
+ for (iterator it = begin(); it != end(); it++)
+ if ((*it)->getOwner() == old_owner)
+ (*it)->setOwner(new_owner);
+}
+
+// End of file