1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005 Ulf Lorenz
3 // Copyright (C) 2004 John Farrell
4 // Copyright (C) 2005 Andrea Paternesi
5 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
6 // Copyright (C) 2007 Ole Laursen
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Library General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include <sigc++/functors/mem_fun.h>
27 #include "playerlist.h"
29 #include "xmlhelper.h"
32 #include "armyprodbase.h"
35 #include "PathCalculator.h"
37 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
40 std::string Citylist::d_tag = "citylist";
42 Citylist* Citylist::s_instance = 0;
44 Citylist* Citylist::getInstance()
47 s_instance = new Citylist();
52 Citylist* Citylist::getInstance(XML_Helper* helper)
57 s_instance = new Citylist(helper);
61 void Citylist::deleteInstance()
73 Citylist::Citylist(XML_Helper* helper)
75 // simply ask the helper to inform us when a city tag is opened
76 helper->registerTag(City::d_tag, sigc::mem_fun(this, &Citylist::load));
83 int Citylist::countCities() const
87 for (const_iterator it = begin(); it != end(); it++)
97 int Citylist::countCities(Player* player) const
101 for (const_iterator it = begin(); it != end(); it++)
103 if ((*it)->isBurnt())
105 if ((*it)->getOwner() == player) cities++;
111 void Citylist::collectTaxes(Player* p) const
114 for (const_iterator it = begin(); it != end(); it++)
115 if ((*it)->getOwner() == p && (*it)->isBurnt() == false)
116 p->addGold((*it)->getGold());
120 //calculate the amount of money new armies will cost in the upcoming turn.
121 guint32 Citylist::calculateUpcomingUpkeep(Player *p) const
124 for (const_iterator it = begin(); it != end(); it++)
125 if ((*it)->getOwner() == p && (*it)->isBurnt() == false)
127 if ((*it)->getDuration() == 1)
129 int slot =(*it)->getActiveProductionSlot();
132 const ArmyProdBase *a = (*it)->getProductionBase(slot);
133 total += a->getUpkeep();
134 total += a->getProductionCost();
140 void Citylist::nextTurn(Player* p)
142 debug("next_turn(" <<p->getName() <<")");
144 // Because players are nextTurn'd before cities, the income, treasury,
145 // and upkeep are calculated already for the upcoming round.
147 //we've already collected taxes this round, so hopefully our
148 //treasury has enough money to pay our city upkeep.
150 guint32 cost_of_new_armies = calculateUpcomingUpkeep(p);
151 if (p->getGold() < (int)cost_of_new_armies)
153 int diff = cost_of_new_armies - p->getGold();
154 //then we have to turn off enough production to make up for diff
156 for (iterator it = begin(); it != end(); it++)
158 if ((*it)->isBurnt() == true)
160 if ((*it)->getOwner() != p)
162 int slot =(*it)->getActiveProductionSlot();
165 const ArmyProdBase *a = (*it)->getProductionBase(slot);
166 diff -= a->getUpkeep();
168 p->cityTooPoorToProduce((*it), slot);
174 // This iteration adds the city production to the player
175 for (iterator it = begin(); it != end(); it++)
177 if ((*it)->getOwner() == p)
183 static bool isFogged(void *object)
185 return ((City*)object)->isVisible(Playerlist::getViewingplayer()) == false;
188 static bool isBurnt(void *object)
190 return ((City*)object)->isBurnt();
193 static bool isNotOwnedByNeutral(void *object)
195 return ((City*)object)->getOwner() != Playerlist::getInstance()->getNeutral();
198 static bool isNotOwnedByActivePlayer(void *object)
200 return ((City*)object)->getOwner() != Playerlist::getActiveplayer();
203 static bool isOwnedByActivePlayer(void *object)
205 return ((City*)object)->getOwner() == Playerlist::getActiveplayer();
208 static bool isNotOwnedByEnemy(void *object)
210 Player *p = Playerlist::getActiveplayer();
213 City *city = ((City*)object);
214 if (city->getOwner() != p &&
215 p->getDiplomaticState(city->getOwner()) == Player::AT_WAR)
220 static bool canNotAcceptMoreVectoring(void *object)
222 City *c = ((City*)object);
223 guint32 num = Citylist::getInstance()->countCitiesVectoringTo(c);
224 if (num < MAX_CITIES_VECTORED_TO_ONE_CITY)
229 City* Citylist::getNearestEnemyCity(const Vector<int>& pos) const
231 std::list<bool (*)(void *)> filters;
232 filters.push_back(isBurnt);
233 filters.push_back(isNotOwnedByEnemy);
234 return getNearestObject(pos, &filters);
237 City* Citylist::getClosestEnemyCity(const Stack *stack) const
239 std::list<bool (*)(void *)> filters;
240 filters.push_back(isBurnt);
241 filters.push_back(isNotOwnedByEnemy);
242 return getClosestObject(stack, &filters);
245 City* Citylist::getClosestForeignCity(const Stack *stack) const
247 std::list<bool (*)(void *)> filters;
248 filters.push_back(isBurnt);
249 filters.push_back(isOwnedByActivePlayer);
250 return getClosestObject(stack, &filters);
253 City* Citylist::getNearestForeignCity(const Vector<int>& pos) const
255 std::list<bool (*)(void *)> filters;
256 filters.push_back(isBurnt);
257 filters.push_back(isOwnedByActivePlayer);
258 return getNearestObject(pos, &filters);
261 City* Citylist::getNearestCity(const Vector<int>& pos, int dist) const
263 City *c = getNearestCity(pos);
266 if (c->getPos().x <= pos.x + dist && c->getPos().x >= pos.x - dist &&
267 c->getPos().y <= pos.y + dist && c->getPos().y >= pos.y - dist)
272 City* Citylist::getNearestFriendlyCity(const Vector<int>& pos, int dist) const
274 City *c = getNearestFriendlyCity(pos);
277 if (c->getPos().x <= pos.x + dist && c->getPos().x >= pos.x - dist &&
278 c->getPos().y <= pos.y + dist && c->getPos().y >= pos.y - dist)
283 City* Citylist::getNearestFriendlyCity(const Vector<int>& pos) const
285 Player* p = Playerlist::getInstance()->getActiveplayer();
286 return getNearestCity (pos, p);
289 City* Citylist::getNearestCity(const Vector<int>& pos, Player *p) const
292 const_iterator diffit;
294 for (const_iterator it = begin(); it != end(); ++it)
296 if ((*it)->isBurnt())
299 if ((*it)->getOwner() == p)
301 Vector<int> p = (*it)->getPos();
302 int delta = abs(p.x - pos.x);
303 if (delta < abs(p.y - pos.y))
304 delta = abs(p.y - pos.y);
306 if ((diff > delta) || (diff == -1))
314 if (diff == -1) return 0;
318 City* Citylist::getClosestCity(const Stack *stack, Player *p) const
321 const_iterator diffit;
322 PathCalculator pc(stack, true, 0, 0);
324 for (const_iterator it = begin(); it != end(); ++it)
326 if ((*it)->isBurnt())
329 if ((*it)->getOwner() == p)
331 int delta = pc.calculate((*it)->getPos());
335 if ((diff > delta) || (diff == -1))
343 if (diff == -1) return 0;
347 City* Citylist::getClosestFriendlyCity(const Stack *stack) const
349 Player* p = Playerlist::getInstance()->getActiveplayer();
350 return getClosestCity (stack, p);
352 City* Citylist::getClosestCity(const Stack *stack) const
354 std::list<bool (*)(void *)> filters;
355 filters.push_back(isBurnt);
356 return getClosestObject(stack, &filters);
359 City* Citylist::getNearestCity(const Vector<int>& pos) const
361 std::list<bool (*)(void *)> filters;
362 filters.push_back(isBurnt);
363 return getNearestObject(pos, &filters);
366 City* Citylist::getNearestVisibleCity(const Vector<int>& pos) const
368 std::list<bool (*)(void *)> filters;
369 filters.push_back(isBurnt);
370 filters.push_back(isFogged);
371 return getNearestObject(pos, &filters);
374 City* Citylist::getNearestVisibleCity(const Vector<int>& pos, int dist) const
376 City *c = getNearestVisibleCity(pos);
379 if (c->getPos().x <= pos.x + dist && c->getPos().x >= pos.x - dist &&
380 c->getPos().y <= pos.y + dist && c->getPos().y >= pos.y - dist)
385 City* Citylist::getNearestVisibleFriendlyCity(const Vector<int>& pos, int dist) const
387 City *c = getNearestFriendlyCity(pos);
390 if (c->getPos().x <= pos.x + dist && c->getPos().x >= pos.x - dist &&
391 c->getPos().y <= pos.y + dist && c->getPos().y >= pos.y - dist)
397 City* Citylist::getNearestVisibleFriendlyCity(const Vector<int>& pos) const
399 std::list<bool (*)(void *)> filters;
400 filters.push_back(isBurnt);
401 filters.push_back(isFogged);
402 filters.push_back(isNotOwnedByActivePlayer);
403 return getNearestObject(pos, &filters);
406 City* Citylist::getNearestNeutralCity(const Vector<int>& pos) const
408 std::list<bool (*)(void *)> filters;
409 filters.push_back(isBurnt);
410 filters.push_back(isNotOwnedByNeutral);
411 return getNearestObject(pos, &filters);
414 City* Citylist::getNearestFriendlyVectorableCity(const Vector<int>& pos) const
416 std::list<bool (*)(void *)> filters;
417 filters.push_back(isBurnt);
418 filters.push_back(isNotOwnedByActivePlayer);
419 filters.push_back(canNotAcceptMoreVectoring);
420 return getNearestObject(pos, &filters);
423 City* Citylist::getFirstCity(Player* p) const
425 for (const_iterator it = begin(); it != end(); it++)
426 if ((*it)->getOwner() == p)
432 bool Citylist::save(XML_Helper* helper) const
436 retval &= helper->openTag(Citylist::d_tag);
438 for (const_iterator it = begin(); it != end(); it++)
441 retval &= helper->closeTag();
446 bool Citylist::load(std::string tag, XML_Helper* helper)
448 if (tag == City::d_tag)
450 Cityset *cs = GameMap::getInstance()->getCityset();
451 City *c = new City(helper, cs->getCityTileWidth());
458 void Citylist::changeOwnership(Player *old_owner, Player *new_owner)
460 for (iterator it = begin(); it != end(); it++)
461 if ((*it)->getOwner() == old_owner)
463 (*it)->setOwner(new_owner);
464 if ((*it)->isCapital())
465 if ((*it)->getCapitalOwner() == old_owner)
466 (*it)->setCapitalOwner(new_owner);
470 void Citylist::stopVectoringTo(City *c)
472 for (iterator it = begin(); it != end(); it++)
474 if ((*it)->isBurnt() == true)
476 if ((*it)->getVectoring() == Vector<int>(-1,-1))
478 if (c->contains((*it)->getVectoring()))
479 (*it)->setVectoring(Vector<int>(-1,-1));
484 bool Citylist::isVectoringTarget(City *target) const
486 for (const_iterator it = begin(); it != end(); it++)
488 if ((*it)->getOwner() != target->getOwner())
490 if (target->contains((*it)->getVectoring()))
496 std::list<City*> Citylist::getCitiesVectoringTo(Vector<int> target) const
498 std::list<City*> cities;
499 for (const_iterator it = begin(); it != end(); it++)
501 if (target == (*it)->getVectoring())
502 cities.push_back((*it));
507 std::list<City*> Citylist::getCitiesVectoringTo(City *target) const
509 std::list<City*> cities;
510 for (const_iterator it = begin(); it != end(); it++)
512 if ((*it)->getOwner() != target->getOwner())
514 if (target->contains((*it)->getVectoring()))
515 cities.push_back((*it));
520 City* Citylist::getNearestCityPast(const Vector<int>& pos, int dist) const
522 std::list<bool (*)(void *)> filters;
523 filters.push_back(isBurnt);
524 return getNearestObjectAfter(pos, dist, &filters);
527 guint32 Citylist::countCitiesVectoringTo(const City *dest) const
530 for (const_iterator it = begin(); it != end(); it++)
533 if (c->getOwner() != dest->getOwner())
535 if (c->getVectoring() == dest->getPos())
542 std::list<City*> Citylist::getNearestFriendlyCities(Player *player, Vector<int> pos) const
544 std::list<City*> cities;
545 for (const_iterator it = begin(); it != end(); it++)
548 if (c->getOwner() != player)
550 if (c->isBurnt() == true)
554 if (cities.size() == 0)
556 std::list<int> distances;
558 if (pos == Vector<int>(-1,-1))
559 pos = getFirstCity(player)->getPos();
561 for (std::list<City*>::iterator it = cities.begin(); it != cities.end(); it++)
562 distances.push_back(dist((*it)->getNearestPos(pos), pos));
571 std::list<int>::iterator dit = distances.begin();
572 std::list<int>::iterator dnextit = distances.begin();
575 std::list<City*>::iterator it = cities.begin();
576 std::list<City*>::iterator nextit = it;
579 for (; nextit != cities.end(); it++, nextit++, dit++, dnextit++)
580 if ((*dit) > (*dnextit))
582 // exchange the items in both lists
585 City* tmp = (*nextit);
586 cities.erase(nextit);
588 it = cities.insert(nextit, tmp);
590 int val = (*dnextit);
591 distances.erase(dnextit);
593 dit = distances.insert(dnextit, val);
599 City *Citylist::getCapitalCity(Player *player) const
601 for (const_iterator it = begin(); it != end(); it++)
604 if (c->getCapitalOwner() == player)