1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004 John Farrell
4 // Copyright (C) 2005 Andrea Paternesi
5 // Copyright (C) 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
26 #include <sigc++/functors/mem_fun.h>
28 #include "playerlist.h"
29 #include "armysetlist.h"
33 #include "vectoredunitlist.h"
34 #include "stacklist.h"
35 #include "xmlhelper.h"
38 #include "stacklist.h"
40 #include "real_player.h"
44 #include "network_player.h"
49 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
52 std::string Playerlist::d_tag = "playerlist";
53 Playerlist* Playerlist::s_instance = 0;
54 Player* Playerlist::d_activeplayer = 0;
55 Player* Playerlist::viewingplayer = 0;
57 Playerlist* Playerlist::getInstance()
60 s_instance = new Playerlist();
65 Playerlist* Playerlist::getInstance(XML_Helper* helper)
70 s_instance = new Playerlist(helper);
75 void Playerlist::deleteInstance()
84 Playerlist::Playerlist()
91 Playerlist::Playerlist(XML_Helper* helper)
96 //load data. This consists currently of two values: size (for checking
97 //the size; we don't use it yet) and active(which player is active)
98 //we do it by calling load with playerlist as string
99 load(Playerlist::d_tag, helper);
101 helper->registerTag(Player::d_tag, sigc::mem_fun(this, &Playerlist::load));
104 Playerlist::~Playerlist()
106 iterator it = begin();
111 bool Playerlist::checkPlayers()
115 debug("checkPlayers()");
116 iterator it = begin ();
120 debug("checkPlayers() iter");
121 //ignore the neutral player as well as dead and immortal ones
122 if ((*it) == d_neutral || (*it)->isDead() || (*it)->isImmortal())
124 debug("checkPlayers() dead?");
129 if (!Citylist::getInstance()->countCities((*it)))
131 debug("checkPlayers() city?");
132 iterator nextit = it;
136 if (getNoOfPlayers() == 1)
138 splayerDead.emit(*it);
143 it = nextit; // do this at the end to catch abuse of invalid it
145 debug("checkPlayers() inc");
152 void Playerlist::nextPlayer()
154 debug("nextPlayer()");
164 for (it = begin(); it != end(); ++it)
166 if ((*it) == d_activeplayer)
174 // in case we have got a dead player, continue iterating. This breaks
175 // if we have ONLY dead players which we assume never happens.
176 while ((it == end()) || ((*it)->isDead()))
186 d_activeplayer = (*it);
187 viewingplayer = (*it);
188 debug("got player: " <<d_activeplayer->getName())
191 Player* Playerlist::getPlayer(string name) const
193 debug("getPlayer()");
194 for (const_iterator it = begin(); it != end(); ++it)
196 if ((*it)->getName() == name) return (*it);
201 Player* Playerlist::getPlayer(guint32 id) const
203 IdMap::const_iterator it = d_id.find(id);
205 if (it == d_id.end())
210 guint32 Playerlist::getNoOfPlayers() const
212 unsigned int number = 0;
214 for (const_iterator it = begin(); it != end(); it++)
216 if (((*it) != d_neutral) && !(*it)->isDead())
223 Player* Playerlist::getFirstLiving() const
225 for (const_iterator it = begin(); ; it++)
226 if (!(*it)->isDead() && *it != d_neutral)
230 bool Playerlist::save(XML_Helper* helper) const
232 //to prevent segfaults
234 d_activeplayer = (*begin());
238 retval &= helper->openTag(Playerlist::d_tag);
239 retval &= helper->saveData("active", d_activeplayer->getId());
240 retval &= helper->saveData("neutral", d_neutral->getId());
242 for (const_iterator it = begin(); it != end(); it++)
243 retval &= (*it)->save(helper);
245 retval &= helper->closeTag();
250 void Playerlist::add(Player *player)
253 d_id[player->getId()] = player;
255 bool Playerlist::load(string tag, XML_Helper* helper)
257 static guint32 active = 0;
258 static guint32 neutral = 0;
260 if (tag == Playerlist::d_tag) //only called in the constructor
262 helper->getData(active, "active");
263 helper->getData(neutral, "neutral");
267 if (tag != Player::d_tag)
270 Player* p = Player::loadPlayer(helper);
277 //set neutral and active
278 if (p->getId() == neutral)
280 if (p->getId() == active)
283 viewingplayer = d_activeplayer;
288 Playerlist::iterator Playerlist::flErase(Playerlist::iterator it)
290 if ((*it) == d_neutral)
303 bool compareDiplomaticScores (const struct rankable_t lhs,
304 const struct rankable_t rhs)
306 /* make ties prefer normal player order */
307 if (lhs.score == rhs.score)
308 return lhs.player->getId() > rhs.player->getId();
310 return lhs.score < rhs.score;
312 void Playerlist::calculateDiplomaticRankings()
315 const char* titles[MAX_PLAYERS] =
327 //determine the rank for each player
328 //add up the scores for all living players, and sort
329 std::list<struct rankable_t> rankables;
330 for (iterator pit = begin (); pit != end (); pit++)
332 if ((*pit) == d_neutral)
334 if ((*pit)->isDead () == true)
336 struct rankable_t rankable;
338 for (iterator it = begin (); it != end (); it++)
340 if ((*it) == d_neutral)
342 if ((*it)->isDead () == true)
346 rankable.score += (*it)->getDiplomaticScore(*pit);
348 rankable.player = *pit;
349 rankables.push_back(rankable);
351 rankables.sort (compareDiplomaticScores);
352 std::reverse (rankables.begin (), rankables.end ());
355 for (std::list<struct rankable_t>::iterator rit = rankables.begin ();
356 rit != rankables.end (); rit++)
358 (*rit).player->setDiplomaticRank(i);
362 // given the rankings, what are the titles?
363 // the titles are depleted from the middle as players die.
364 // 7 means deplete first, 0 means deplete last.
365 unsigned int deplete[MAX_PLAYERS] = { 0, 2, 4, 6, 7, 5, 3, 1 };
367 unsigned int numAlive = countPlayersAlive ();
368 // okay, we take the first numAlive titles
370 std::vector<std::string> available_titles;
371 for (i = numAlive; i < MAX_PLAYERS ; i++)
373 for (unsigned int j = 0; j < MAX_PLAYERS; j++)
379 for (unsigned int i = 0; i < MAX_PLAYERS; i++)
381 if (titles[i][0] != '\0')
382 available_titles.push_back (std::string(titles[i]));
385 for (const_iterator it = begin (); it != end (); it++)
387 if ((*it) == d_neutral)
389 if ((*it)->isDead () == true)
391 guint32 rank = (*it)->getDiplomaticRank();
392 // recall that the first rank is 1, and not 0.
393 (*it)->setDiplomaticTitle (available_titles[rank - 1]);
399 void Playerlist::calculateWinners()
402 guint32 total_gold = 0;
403 guint32 total_armies = 0;
404 guint32 total_cities = 0;
405 for (const_iterator it = begin(); it != end(); it++)
407 if ((*it) == d_neutral)
409 if ((*it)->isDead() == true)
411 total_gold += (*it)->getGold();
412 total_armies += (*it)->getStacklist()->countArmies();
414 total_cities = Citylist::getInstance()->size();
416 for (const_iterator it = begin(); it != end(); it++)
418 if ((*it) == d_neutral)
420 if ((*it)->isDead() == true)
423 Citylist *clist = Citylist::getInstance();
424 float city_component = (float)
425 ((float) clist->countCities(*it)/ (float)total_cities) * 70.0;
426 float gold_component = (float)
427 ((float) (*it)->getGold() / (float)total_gold) * 10.0;
428 float army_component = (float)
429 ((float) (*it)->getStacklist()->countArmies() /
430 (float)total_armies) * 20.0;
431 score = (guint32) (city_component + gold_component + army_component);
432 History_Score *item = new History_Score();
433 item->fillData(score);
434 (*it)->addHistory(item);
436 History_GoldTotal* gold = new History_GoldTotal();
437 gold->fillData((*it)->getGold());
438 (*it)->addHistory(gold);
444 guint32 Playerlist::countHumanPlayersAlive() const
447 for (const_iterator it = begin(); it != end(); it++)
448 if ((*it)->isDead() == false && (*it)->getType() == Player::HUMAN)
453 guint32 Playerlist::countPlayersAlive () const
455 guint32 numAlive = 0;
457 for (const_iterator it = begin (); it != end (); it++)
459 if ((*it) == d_neutral)
461 if ((*it)->isDead () == true)
468 void Playerlist::negotiateDiplomacy()
470 // hold diplomatic talks, and determine diplomatic outcomes
471 for (iterator pit = begin(); pit != end(); pit++)
473 if ((*pit)->isDead())
476 if ((*pit) == getNeutral())
479 for (iterator it = begin(); it != end(); it++)
485 if ((*it) == getNeutral())
491 Player::DiplomaticState old_state = (*pit)->getDiplomaticState(*it);
492 Player::DiplomaticState new_state = (*pit)->negotiateDiplomacy(*it);
493 (*pit)->declareDiplomacy (new_state, (*it));
494 (*pit)->proposeDiplomacy (Player::NO_PROPOSAL, (*it));
495 (*it)->declareDiplomacy (new_state, (*pit));
496 (*it)->proposeDiplomacy (Player::NO_PROPOSAL, (*pit));
497 if (old_state != new_state)
501 if (new_state == Player::AT_PEACE)
503 //their view of me goes up
504 them->improveDiplomaticRelationship(me, 1);
505 //their allies think better of me
506 me->improveAlliesRelationship (them, 1, Player::AT_PEACE);
507 //their enemies think less of me
508 them->deteriorateAlliesRelationship (me, 1, Player::AT_WAR);
510 History_DiplomacyPeace *item = new History_DiplomacyPeace();
512 (*pit)->addHistory(item);
514 else if (new_state == Player::AT_WAR)
516 //their view of me goes down
517 them->deteriorateDiplomaticRelationship(me, 1);
518 //their allies view of me goes down
519 them->deteriorateAlliesRelationship(me, 1, Player::AT_PEACE);
520 //their enemies view of me goes up
521 me->improveAlliesRelationship(them, 1, Player::AT_WAR);
523 History_DiplomacyWar *item = new History_DiplomacyWar();
524 item->fillData(them);
525 me->addHistory(item);
532 void Playerlist::swap(Player *old_player, Player *new_player)
534 std::replace(begin(), end(), old_player, new_player);
535 //point cities to the new owner
536 Citylist *clist = Citylist::getInstance();
537 clist->changeOwnership (old_player, new_player);
538 Ruinlist *rlist = Ruinlist::getInstance();
539 rlist->changeOwnership (old_player, new_player);
540 VectoredUnitlist *vlist = VectoredUnitlist::getInstance();
541 vlist->changeOwnership (old_player, new_player);
542 AI_Analysis::changeOwnership(old_player, new_player);
543 if (old_player == d_activeplayer)
545 d_activeplayer = new_player;
546 d_activeplayer->setActivestack(0);
548 if (old_player == viewingplayer)
549 viewingplayer = new_player;
550 d_id[new_player->getId()] = new_player;
551 /* note, we don't have to change the player associated with flag graphics
552 because it's stored as an id. */
555 bool Playerlist::randomly(const Player *lhs, const Player *rhs)
557 Playerlist *pl = Playerlist::getInstance();
558 if (lhs == pl->getNeutral())
566 bool Playerlist::inOrderOfId(const Player *lhs, const Player *rhs)
568 if (lhs->getId() > rhs->getId())
574 //randomly reorder the player list, but keeping neutral last.
575 void Playerlist::randomizeOrder()
578 d_activeplayer = NULL;
579 viewingplayer = NULL;
582 void Playerlist::nextRound(bool diplomacy, bool *surrender_already_offered)
587 negotiateDiplomacy();
588 calculateDiplomaticRankings();
595 if (countHumanPlayersAlive() == 1 &&
596 *surrender_already_offered == 0)
598 for (iterator it = begin(); it != end(); it++)
600 if ((*it)->getType() == Player::HUMAN)
602 Citylist *cl = Citylist::getInstance();
603 int target_level = cl->size() / 2;
604 if (cl->countCities(*it) > target_level)
606 *surrender_already_offered = 1;
607 ssurrender.emit(*it);
615 void Playerlist::syncPlayer(GameParameters::Player player)
617 Player *p = getPlayer((guint32)player.id);
620 //player was off originally, but now it's on
621 guint32 armyset = d_neutral->getArmyset();
622 int width = d_neutral->getFogMap()->getWidth();
623 int height = d_neutral->getFogMap()->getHeight();
624 int gold = d_neutral->getGold();
625 GameMap *gm = GameMap::getInstance();
628 case GameParameters::Player::HUMAN:
629 p = new RealPlayer(player.name, armyset,
630 gm->getShieldset()->getColor(player.id),
631 width, height, Player::HUMAN, player.id);
633 case GameParameters::Player::EASY:
634 p = new AI_Fast(player.name, armyset,
635 gm->getShieldset()->getColor(player.id),
636 width, height, player.id);
638 case GameParameters::Player::HARD:
639 p = new AI_Smart(player.name, armyset,
640 gm->getShieldset()->getColor(player.id),
641 width, height, player.id);
643 case GameParameters::Player::OFF:
644 //was off, now it's still off.
647 cerr << "could not make player with type " << player.type;
657 d_activeplayer = getFirstLiving();
658 viewingplayer = d_activeplayer;
663 p->setName(player.name);
667 case GameParameters::Player::HUMAN:
668 if (p->getType() != Player::HUMAN)
670 RealPlayer *new_p = new RealPlayer(*p);
674 case GameParameters::Player::EASY:
675 if (p->getType() != Player::AI_FAST)
677 AI_Fast *new_p = new AI_Fast(*p);
681 case GameParameters::Player::HARD:
682 if (p->getType() != Player::AI_SMART)
684 AI_Smart *new_p = new AI_Smart(*p);
688 case GameParameters::Player::OFF:
690 //point owned cities to neutral
691 Citylist *clist = Citylist::getInstance();
692 clist->changeOwnership (p, d_neutral);
693 //point owned ruins to neutral
694 Ruinlist *rlist = Ruinlist::getInstance();
695 rlist->changeOwnership (p, d_neutral);
696 //now get rid of the player entirely
697 flErase(find(begin(), end(), p));
701 cerr << "could not sync player with type " << player.type;
707 d_activeplayer = getFirstLiving();
708 viewingplayer = d_activeplayer;
712 void Playerlist::syncPlayers(std::vector<GameParameters::Player> players)
715 std::vector<GameParameters::Player>::const_iterator i = players.begin();
716 for (; i != players.end(); i++)
721 void Playerlist::turnHumansIntoNetworkPlayers()
723 for (iterator i = begin(); i != end(); i++)
725 if ((*i)->getType() == Player::HUMAN)
727 NetworkPlayer *new_p = new NetworkPlayer(**i);
736 void Playerlist::turnHumansInto(Player::Type type, int number_of_players)
739 for (iterator i = begin(); i != end(); i++)
741 if (count >= number_of_players && number_of_players > 0)
743 if ((*i)->getType() == Player::HUMAN)
747 case Player::AI_DUMMY:
749 AI_Dummy *new_p = new AI_Dummy(**i);
757 case Player::AI_FAST:
759 AI_Fast *new_p = new AI_Fast(**i);
767 case Player::AI_SMART:
769 AI_Smart *new_p = new AI_Smart(**i);
777 case Player::NETWORKED:
779 NetworkPlayer *new_p = new NetworkPlayer(**i);
794 std::list<guint32> given_turn_order;
795 bool Playerlist::inGivenOrder(const Player *lhs, const Player *rhs)
797 if (given_turn_order.size() == 0)
801 for(std::list<guint32>::iterator it = given_turn_order.begin();
802 it != given_turn_order.end(); it++)
805 if (lhs->getId() == (*it))
808 int lhs_rank = count;
810 for(std::list<guint32>::iterator it = given_turn_order.begin();
811 it != given_turn_order.end(); it++)
814 if (rhs->getId() == (*it))
817 int rhs_rank = count;
818 return lhs_rank > rhs_rank;
822 void Playerlist::reorder(std::list<guint32> order)
824 given_turn_order = order;
826 given_turn_order.clear();
827 d_activeplayer = getFirstLiving();
828 viewingplayer = d_activeplayer;
831 std::list<History *>Playerlist::getHistoryForHeroId(guint32 id) const
833 std::list<History*> no_events;
834 for (const_iterator it = begin(); it != end(); ++it)
836 std::list<History *>events = (*it)->getHistoryForHeroId(id);
837 if (events.size() > 0)
843 void Playerlist::surrender()
845 //the last human player has accepted surrender
846 for (iterator it = begin(); it != end(); it++)
848 if ((*it)->getType() != Player::HUMAN)
850 (*it)->setSurrendered(true);
855 bool Playerlist::isEndOfRound() const
857 //check to see if all players have moved this round.
858 //do all players have the same number of history:end_turn events?
859 if (d_activeplayer == NULL)
861 guint32 count = d_activeplayer->countEndTurnHistoryEntries();
862 for (const_iterator it = begin(); it != end(); it++)
864 if (*it == d_activeplayer)
866 if (count != (*it)->countEndTurnHistoryEntries())
872 void Playerlist::setWinningPlayer(Player *winner)
875 d_activeplayer = winner;
878 int Playerlist::countFightsThisTurn() const
881 for (const_iterator it = begin(); it != end(); it++)
882 count += (*it)->countFightsThisTurn();
886 int Playerlist::countMovesThisTurn() const
889 for (const_iterator it = begin(); it != end(); it++)
890 count += (*it)->countMovesThisTurn();
894 Player *Playerlist::getWinningPlayer() const
896 guint32 best_score = 0;
897 Player *winning_player = NULL;
898 for (const_iterator it = begin(); it != end(); it++)
901 if (p->isDead() == false)
903 if (p == getNeutral())
905 if (p->getScore() >= best_score)
907 best_score = p->getScore();
911 return winning_player;