initial commit, lordsawar source, slightly modified
[lordsawar] / src / playerlist.cpp
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
7 //
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.
12 //
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.
17 //
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 
21 //  02110-1301, USA.
22
23 #include "config.h"
24 #include <sstream>
25 #include <algorithm>
26 #include <sigc++/functors/mem_fun.h>
27
28 #include "playerlist.h"
29 #include "armysetlist.h"
30
31 #include "citylist.h"
32 #include "ruinlist.h"
33 #include "vectoredunitlist.h"
34 #include "stacklist.h"
35 #include "xmlhelper.h"
36 #include "history.h"
37 #include "citylist.h"
38 #include "stacklist.h"
39 #include "FogMap.h"
40 #include "real_player.h"
41 #include "ai_smart.h"
42 #include "ai_fast.h"
43 #include "ai_dummy.h"
44 #include "network_player.h"
45 #include "GameMap.h"
46
47 using namespace std;
48
49 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
50 #define debug(x)
51
52 std::string Playerlist::d_tag = "playerlist";
53 Playerlist* Playerlist::s_instance = 0;
54 Player* Playerlist::d_activeplayer = 0;
55 Player* Playerlist::viewingplayer = 0;
56
57 Playerlist* Playerlist::getInstance()
58 {
59     if (s_instance == 0)
60         s_instance = new Playerlist();
61
62     return s_instance;
63 }
64
65 Playerlist* Playerlist::getInstance(XML_Helper* helper)
66 {
67     if (s_instance)
68         deleteInstance();
69
70     s_instance = new Playerlist(helper);
71
72     return s_instance;
73 }
74
75 void Playerlist::deleteInstance()
76 {
77     if (s_instance)
78     {
79         delete s_instance;
80         s_instance = 0;
81     }
82 }
83
84 Playerlist::Playerlist()
85     :d_neutral(0)
86 {
87     d_activeplayer = 0;
88     viewingplayer = 0;
89 }
90
91 Playerlist::Playerlist(XML_Helper* helper)
92     :d_neutral(0)
93 {
94     d_activeplayer=0;
95     viewingplayer=0;
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);
100
101     helper->registerTag(Player::d_tag, sigc::mem_fun(this, &Playerlist::load));
102 }
103
104 Playerlist::~Playerlist()
105 {
106     iterator it = begin();
107     while (!empty())
108         it = flErase(it);
109 }
110
111 bool Playerlist::checkPlayers()
112 {
113     bool last = false;
114     bool dead = false;
115     debug("checkPlayers()");
116     iterator it = begin ();
117           
118     while (it != end ())
119     {
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())
123         {
124             debug("checkPlayers() dead?");
125             it++;
126             continue;
127         }
128
129         if (!Citylist::getInstance()->countCities((*it)))
130         {
131             debug("checkPlayers() city?");
132             iterator nextit = it;
133             nextit++;
134
135             (*it)->kill();
136             if (getNoOfPlayers() == 1)
137               last = true;
138             splayerDead.emit(*it);
139             dead = true;
140             if (last)
141               break;
142
143             it = nextit;    // do this at the end to catch abuse of invalid it
144         } else {
145             debug("checkPlayers() inc");
146             ++it;
147         }
148     }
149   return dead;
150 }
151
152 void Playerlist::nextPlayer()
153 {
154     debug("nextPlayer()");
155
156     iterator it;
157
158     if (!d_activeplayer)
159     {
160         it = begin();
161     }
162     else
163     {
164         for (it = begin(); it != end(); ++it)
165         {
166             if ((*it) == d_activeplayer)
167             {
168                 it++;
169                 break;
170             }
171         }
172     }
173
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()))
177     {
178         if (it == end())
179         {
180             it = begin();
181             continue;
182         }
183         it++;
184     }
185
186     d_activeplayer = (*it);
187     viewingplayer = (*it);
188     debug("got player: " <<d_activeplayer->getName())
189 }
190
191 Player* Playerlist::getPlayer(string name) const
192 {
193     debug("getPlayer()");
194     for (const_iterator it = begin(); it != end(); ++it)
195     {
196         if ((*it)->getName() == name) return (*it);
197     }
198     return 0;
199 }
200
201 Player* Playerlist::getPlayer(guint32 id) const
202 {
203   IdMap::const_iterator it = d_id.find(id);
204
205   if (it == d_id.end())
206     return NULL;
207   return  (*it).second;
208 }
209
210 guint32 Playerlist::getNoOfPlayers() const
211 {
212     unsigned int number = 0;
213
214     for (const_iterator it = begin(); it != end(); it++)
215     {
216         if (((*it) != d_neutral) && !(*it)->isDead())
217             number++;
218     }
219
220     return number;
221 }
222
223 Player* Playerlist::getFirstLiving() const
224 {
225     for (const_iterator it = begin(); ; it++)
226         if (!(*it)->isDead() && *it != d_neutral)
227             return (*it);
228 }
229
230 bool Playerlist::save(XML_Helper* helper) const
231 {
232     //to prevent segfaults
233     if (!d_activeplayer)
234         d_activeplayer = (*begin());
235
236     bool retval = true;
237
238     retval &= helper->openTag(Playerlist::d_tag);
239     retval &= helper->saveData("active", d_activeplayer->getId());
240     retval &= helper->saveData("neutral", d_neutral->getId());
241
242     for (const_iterator it = begin(); it != end(); it++)
243         retval &= (*it)->save(helper);
244
245     retval &= helper->closeTag();
246
247     return retval;
248 }
249
250 void Playerlist::add(Player *player)
251 {
252   push_back(player);
253   d_id[player->getId()] = player;
254 }
255 bool Playerlist::load(string tag, XML_Helper* helper)
256 {
257     static guint32 active = 0;
258     static guint32 neutral = 0;
259
260     if (tag == Playerlist::d_tag) //only called in the constructor
261     {
262         helper->getData(active, "active");
263         helper->getData(neutral, "neutral");
264         return true;
265     }
266
267     if (tag != Player::d_tag)
268         return false;
269
270     Player* p = Player::loadPlayer(helper);
271     if(p == 0)
272         return false;
273
274     //insert player...
275     add(p);
276
277     //set neutral and active
278     if (p->getId() == neutral)
279         d_neutral = p;
280     if (p->getId() == active)
281       d_activeplayer = p;
282
283     viewingplayer = d_activeplayer;
284
285     return true;
286 }
287
288 Playerlist::iterator Playerlist::flErase(Playerlist::iterator it)
289 {
290     if ((*it) == d_neutral)
291         d_neutral = 0;
292
293     delete (*it);
294     return erase (it);
295 }
296
297 struct rankable_t
298 {
299   guint32 score;
300   Player *player;
301 };
302
303 bool compareDiplomaticScores (const struct rankable_t lhs,
304                               const struct rankable_t rhs)
305 {
306   /* make ties prefer normal player order */
307   if (lhs.score == rhs.score) 
308     return lhs.player->getId() > rhs.player->getId();
309   else
310     return lhs.score < rhs.score;
311 }
312 void Playerlist::calculateDiplomaticRankings()
313 {
314   unsigned int i = 0;
315   const char* titles[MAX_PLAYERS] =
316     {
317       _("Statesman"),
318       _("Diplomat"),
319       _("Pragmatist"),
320       _("Politician"),
321       _("Deceiver"),
322       _("Scoundrel"),
323       _("Turncoat"),
324       _("Running Dog"),
325     };
326
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++)
331     {
332       if ((*pit) == d_neutral)
333         continue;
334       if ((*pit)->isDead () == true)
335         continue;
336       struct rankable_t rankable;
337       rankable.score = 0;
338       for (iterator it = begin (); it != end (); it++)
339         {
340           if ((*it) == d_neutral)
341             continue;
342           if ((*it)->isDead () == true)
343             continue;
344           if (*pit == *it)
345             continue;
346           rankable.score += (*it)->getDiplomaticScore(*pit);
347         }
348       rankable.player = *pit;
349       rankables.push_back(rankable);
350     }
351   rankables.sort (compareDiplomaticScores);
352   std::reverse (rankables.begin (), rankables.end ());
353
354   i = 1;
355   for (std::list<struct rankable_t>::iterator rit = rankables.begin (); 
356        rit != rankables.end (); rit++)
357     {
358       (*rit).player->setDiplomaticRank(i);
359       i++;
360     }
361
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 };
366
367   unsigned int numAlive = countPlayersAlive ();
368   // okay, we take the first numAlive titles
369
370   std::vector<std::string> available_titles;
371   for (i = numAlive; i < MAX_PLAYERS ; i++)
372     {
373       for (unsigned int j = 0; j < MAX_PLAYERS; j++)
374         {
375           if (deplete[j] == i)
376             titles[j] = "";
377         }
378     }
379   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
380     {
381       if (titles[i][0] != '\0')
382         available_titles.push_back (std::string(titles[i]));
383     }
384
385   for (const_iterator it = begin (); it != end (); it++)
386     {
387       if ((*it) == d_neutral)
388         continue;
389       if ((*it)->isDead () == true)
390         continue;
391       guint32 rank = (*it)->getDiplomaticRank();
392       // recall that the first rank is 1, and not 0.
393       (*it)->setDiplomaticTitle (available_titles[rank - 1]);
394     }
395
396   return;
397 }
398
399 void Playerlist::calculateWinners()
400 {
401     guint32 score;
402     guint32 total_gold = 0;
403     guint32 total_armies = 0;
404     guint32 total_cities = 0;
405     for (const_iterator it = begin(); it != end(); it++)
406       {
407         if ((*it) == d_neutral)
408           continue;
409         if ((*it)->isDead() == true)
410           continue;
411         total_gold += (*it)->getGold();
412         total_armies += (*it)->getStacklist()->countArmies();
413       }
414     total_cities = Citylist::getInstance()->size();
415
416     for (const_iterator it = begin(); it != end(); it++)
417       {
418         if ((*it) == d_neutral)
419           continue;
420         if ((*it)->isDead() == true)
421           continue;
422
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);
435
436         History_GoldTotal* gold = new History_GoldTotal();
437         gold->fillData((*it)->getGold());
438         (*it)->addHistory(gold);
439       }
440
441     return;
442 }
443
444 guint32 Playerlist::countHumanPlayersAlive() const
445 {
446   guint32 retval = 0;
447   for (const_iterator it = begin(); it != end(); it++)
448     if ((*it)->isDead() == false && (*it)->getType() == Player::HUMAN)
449       retval++;
450   return retval;
451 }
452
453 guint32 Playerlist::countPlayersAlive () const
454 {
455   guint32 numAlive = 0; 
456
457   for (const_iterator it = begin (); it != end (); it++)
458     {
459       if ((*it) == d_neutral)
460         continue;
461       if ((*it)->isDead () == true)
462         continue;
463       numAlive++;
464     }
465   return numAlive;
466 }
467
468 void Playerlist::negotiateDiplomacy()
469 {
470   // hold diplomatic talks, and determine diplomatic outcomes
471   for (iterator pit = begin(); pit != end(); pit++)
472     {
473       if ((*pit)->isDead())
474         continue;
475
476       if ((*pit) == getNeutral())
477         continue;
478   
479       for (iterator it = begin(); it != end(); it++)
480         {
481       
482           if ((*it)->isDead())
483             continue;
484
485           if ((*it) == getNeutral())
486             continue;
487
488           if ((*it) == (*pit))
489             break;
490   
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)
498             {
499               Player *me = *pit;
500               Player *them = *it;
501               if (new_state == Player::AT_PEACE)
502                 {
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);
509
510                   History_DiplomacyPeace *item = new History_DiplomacyPeace();
511                   item->fillData(*it);
512                   (*pit)->addHistory(item);
513                 }
514               else if (new_state == Player::AT_WAR)
515                 {
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);
522
523                   History_DiplomacyWar *item = new History_DiplomacyWar();
524                   item->fillData(them);
525                   me->addHistory(item);
526                 }
527             }
528         }
529     }
530 }
531
532 void Playerlist::swap(Player *old_player, Player *new_player)
533 {
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)
544     {
545       d_activeplayer = new_player;
546       d_activeplayer->setActivestack(0);
547     }
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. */
553 }
554
555 bool Playerlist::randomly(const Player *lhs, const Player *rhs)  
556 {
557   Playerlist *pl = Playerlist::getInstance();
558   if (lhs == pl->getNeutral())
559     return false;
560   if (rand() % 2 == 0)
561     return true;
562   else
563     return false;
564 }
565
566 bool Playerlist::inOrderOfId(const Player *lhs, const Player *rhs)  
567 {
568   if (lhs->getId() > rhs->getId())
569     return false;
570   else
571     return true;
572 }
573
574 //randomly reorder the player list, but keeping neutral last.
575 void Playerlist::randomizeOrder()
576 {
577   sort(randomly);
578   d_activeplayer = NULL;
579   viewingplayer = NULL;
580 }
581
582 void Playerlist::nextRound(bool diplomacy, bool *surrender_already_offered)
583 {
584   // update diplomacy
585   if (diplomacy)
586     {
587       negotiateDiplomacy();
588       calculateDiplomaticRankings();
589     }
590
591   // update winners
592   calculateWinners();
593
594   // offer surrender
595   if (countHumanPlayersAlive() == 1 &&
596       *surrender_already_offered == 0)
597     {
598       for (iterator it = begin(); it != end(); it++)
599         {
600           if ((*it)->getType() == Player::HUMAN)
601             {
602               Citylist *cl = Citylist::getInstance();
603               int target_level = cl->size() / 2;
604               if (cl->countCities(*it) > target_level)
605                 {
606                   *surrender_already_offered = 1;
607                   ssurrender.emit(*it);
608                   break;
609                 }
610             }
611         }
612     }
613 }
614
615 void Playerlist::syncPlayer(GameParameters::Player player)
616 {
617   Player *p = getPlayer((guint32)player.id);
618   if (!p)
619     {
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();
626       switch (player.type)
627         {
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);
632           break;
633         case GameParameters::Player::EASY:
634           p = new AI_Fast(player.name, armyset,
635                           gm->getShieldset()->getColor(player.id),
636                           width, height, player.id);
637           break;
638         case GameParameters::Player::HARD:
639           p = new AI_Smart(player.name, armyset,
640                            gm->getShieldset()->getColor(player.id),
641                            width, height, player.id);
642           break;
643         case GameParameters::Player::OFF:
644           //was off, now it's still off.
645           break;
646         default:
647           cerr << "could not make player with type " << player.type;
648           exit (1);
649           break;
650         }
651       if (p)
652         {
653           p->setGold(gold);
654           add(p);
655
656           sort(inOrderOfId);
657           d_activeplayer = getFirstLiving();
658           viewingplayer = d_activeplayer;
659         }
660       return;
661     }
662   else
663     p->setName(player.name);
664
665   switch (player.type)
666     {
667     case GameParameters::Player::HUMAN:
668       if (p->getType() != Player::HUMAN)
669         {
670           RealPlayer *new_p = new RealPlayer(*p);
671           swap(p, new_p);
672         }
673       break;
674     case GameParameters::Player::EASY:
675       if (p->getType() != Player::AI_FAST)
676         {
677           AI_Fast *new_p = new AI_Fast(*p);
678           swap(p, new_p);
679         }
680       break;
681     case GameParameters::Player::HARD:
682       if (p->getType() != Player::AI_SMART)
683         {
684           AI_Smart *new_p = new AI_Smart(*p);
685           swap(p, new_p);
686         }
687       break;
688     case GameParameters::Player::OFF:
689         {
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));
698         }
699       break;
700     default:
701       cerr << "could not sync player with type " << player.type;
702       exit (1);
703       break;
704     }
705
706   sort(inOrderOfId);
707   d_activeplayer = getFirstLiving();
708   viewingplayer = d_activeplayer;
709   return;
710 }
711
712 void Playerlist::syncPlayers(std::vector<GameParameters::Player> players)
713 {
714
715   std::vector<GameParameters::Player>::const_iterator i = players.begin();
716   for (; i != players.end(); i++)
717     syncPlayer(*i);
718
719 }
720         
721 void Playerlist::turnHumansIntoNetworkPlayers()
722 {
723   for (iterator i = begin(); i != end(); i++)
724     {
725       if ((*i)->getType() == Player::HUMAN)
726         {
727           NetworkPlayer *new_p = new NetworkPlayer(**i);
728           swap((*i), new_p);
729           //delete *i; fixme
730           i = begin();
731           continue;
732         }
733     }
734 }
735
736 void Playerlist::turnHumansInto(Player::Type type, int number_of_players)
737 {
738   int count = 0;
739   for (iterator i = begin(); i != end(); i++)
740     {
741       if (count >= number_of_players && number_of_players > 0)
742         break;
743       if ((*i)->getType() == Player::HUMAN)
744         {
745           switch (type)
746             {
747             case Player::AI_DUMMY:
748                 {
749                   AI_Dummy *new_p = new AI_Dummy(**i);
750                   swap((*i), new_p);
751                   //delete *i; fixme
752                   i = begin();
753                   count++;
754                   continue;
755                 }
756               break;
757             case Player::AI_FAST:
758                 {
759                   AI_Fast *new_p = new AI_Fast(**i);
760                   swap((*i), new_p);
761                   //delete *i; fixme
762                   i = begin();
763                   count++;
764                   continue;
765                 }
766               break;
767             case Player::AI_SMART:
768                 {
769                   AI_Smart *new_p = new AI_Smart(**i);
770                   swap((*i), new_p);
771                   //delete *i; fixme
772                   i = begin();
773                   count++;
774                   continue;
775                 }
776               break;
777             case Player::NETWORKED:
778                 {
779                   NetworkPlayer *new_p = new NetworkPlayer(**i);
780                   swap((*i), new_p);
781                   //delete *i; fixme
782                   i = begin();
783                   count++;
784                   continue;
785                 }
786               break;
787             case Player::HUMAN:
788               break;
789             }
790         }
791     }
792 }
793
794 std::list<guint32> given_turn_order;
795 bool Playerlist::inGivenOrder(const Player *lhs, const Player *rhs)  
796 {
797   if (given_turn_order.size() == 0)
798     return true;
799
800   int count = 0;
801   for(std::list<guint32>::iterator it = given_turn_order.begin(); 
802       it != given_turn_order.end(); it++)
803     {
804       count++;
805       if (lhs->getId() == (*it))
806         break;
807     }
808   int lhs_rank = count;
809   count = 0;
810   for(std::list<guint32>::iterator it = given_turn_order.begin(); 
811       it != given_turn_order.end(); it++)
812     {
813       count++;
814       if (rhs->getId() == (*it))
815         break;
816     }
817   int rhs_rank = count;
818   return lhs_rank > rhs_rank;
819 }
820
821
822 void Playerlist::reorder(std::list<guint32> order)
823 {
824   given_turn_order = order;
825   sort(inGivenOrder);
826   given_turn_order.clear();
827   d_activeplayer = getFirstLiving();
828   viewingplayer = d_activeplayer;
829 }
830
831 std::list<History *>Playerlist::getHistoryForHeroId(guint32 id) const
832 {
833   std::list<History*> no_events;
834   for (const_iterator it = begin(); it != end(); ++it)
835     {
836       std::list<History *>events = (*it)->getHistoryForHeroId(id);
837       if (events.size() > 0)
838         return events;
839     }
840   return no_events;
841 }
842
843 void Playerlist::surrender()
844 {
845   //the last human player has accepted surrender
846   for (iterator it = begin(); it != end(); it++)
847     {
848       if ((*it)->getType() != Player::HUMAN)
849         {
850           (*it)->setSurrendered(true);
851         }
852     }
853 }
854
855 bool Playerlist::isEndOfRound() const
856 {
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)
860     return false;
861   guint32 count = d_activeplayer->countEndTurnHistoryEntries();
862   for (const_iterator it = begin(); it != end(); it++)
863     {
864       if (*it == d_activeplayer)
865         continue;
866       if (count != (*it)->countEndTurnHistoryEntries())
867         return false;
868     }
869   return true;
870 }
871
872 void Playerlist::setWinningPlayer(Player *winner)
873 {
874   //only for humans
875   d_activeplayer = winner;
876 }
877
878 int Playerlist::countFightsThisTurn() const
879 {
880   int count = 0;
881   for (const_iterator it = begin(); it != end(); it++)
882     count += (*it)->countFightsThisTurn();
883   return count;
884 }
885
886 int Playerlist::countMovesThisTurn() const
887 {
888   int count = 0;
889   for (const_iterator it = begin(); it != end(); it++)
890     count += (*it)->countMovesThisTurn();
891   return count;
892 }
893
894 Player *Playerlist::getWinningPlayer() const
895 {
896   guint32 best_score = 0;
897   Player *winning_player = NULL;
898   for (const_iterator it = begin(); it != end(); it++)
899     {
900       Player *p = (*it);
901       if (p->isDead() == false)
902         continue;
903       if (p == getNeutral())
904         continue;
905       if (p->getScore() >= best_score)
906         {
907           best_score = p->getScore();
908           winning_player = p;
909         }
910     }
911   return winning_player;
912 }