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, 2010, 2014, 2015, 2017, 2020 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 <sigc++/functors/mem_fun.h>
26 
27 #include "playerlist.h"
28 #include "armysetlist.h"
29 #include "citylist.h"
30 #include "ruinlist.h"
31 #include "vectoredunitlist.h"
32 #include "xmlhelper.h"
33 #include "history.h"
34 #include "stacklist.h"
35 #include "FogMap.h"
36 #include "real_player.h"
37 #include "ai_smart.h"
38 #include "ai_fast.h"
39 #include "ai_dummy.h"
40 #include "network_player.h"
41 #include "GameMap.h"
42 #include "shieldset.h"
43 #include "shieldsetlist.h"
44 #include "ucompose.hpp"
45 #include "stack.h"
46 #include "rnd.h"
47 
48 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
49 #define debug(x)
50 
51 Glib::ustring Playerlist::d_tag = "playerlist";
52 Playerlist* Playerlist::s_instance = 0;
53 Player* Playerlist::d_activeplayer = 0;
54 Player* Playerlist::viewingplayer = 0;
55 
getInstance()56 Playerlist* Playerlist::getInstance()
57 {
58     if (s_instance == 0)
59         s_instance = new Playerlist();
60 
61     return s_instance;
62 }
63 
getInstance(XML_Helper * helper)64 Playerlist* Playerlist::getInstance(XML_Helper* helper)
65 {
66     if (s_instance)
67         deleteInstance();
68 
69     s_instance = new Playerlist(helper);
70 
71     return s_instance;
72 }
73 
deleteInstance()74 void Playerlist::deleteInstance()
75 {
76     if (s_instance)
77     {
78         delete s_instance;
79         s_instance = 0;
80     }
81 }
82 
Playerlist()83 Playerlist::Playerlist()
84     :d_neutral(0)
85 {
86     d_activeplayer = 0;
87     viewingplayer = 0;
88 }
89 
Playerlist(XML_Helper * helper)90 Playerlist::Playerlist(XML_Helper* helper)
91     :d_neutral(0)
92 {
93     d_activeplayer=0;
94     viewingplayer=0;
95     //load data. This consists currently of two values: size (for checking
96     //the size; we don't use it yet) and active(which player is active)
97     //we do it by calling load with playerlist as string
98     load(Playerlist::d_tag, helper);
99 
100     helper->registerTag(Player::d_tag, sigc::mem_fun(this, &Playerlist::load));
101 }
102 
~Playerlist()103 Playerlist::~Playerlist()
104 {
105     iterator it = begin();
106     while (!empty())
107         it = flErase(it);
108 }
109 
checkPlayers()110 bool Playerlist::checkPlayers()
111 {
112     bool last = false;
113     bool dead = false;
114     debug("checkPlayers()");
115     iterator it = begin ();
116 
117     while (it != end ())
118     {
119         debug("checkPlayers() iter");
120         //ignore the neutral player as well as dead and immortal ones
121         if ((*it) == d_neutral || (*it)->isDead() || (*it)->isImmortal())
122         {
123             debug("checkPlayers() dead?");
124             it++;
125             continue;
126         }
127 
128         if (!Citylist::getInstance()->countCities((*it)))
129         {
130             debug("checkPlayers() city?");
131             iterator nextit = it;
132             nextit++;
133 
134             (*it)->kill();
135 	    if (getNoOfPlayers() == 1)
136 	      last = true;
137             splayerDead.emit(*it);
138             dead = true;
139 	    if (last)
140 	      break;
141 
142             it = nextit;    // do this at the end to catch abuse of invalid it
143         } else {
144             debug("checkPlayers() inc");
145             ++it;
146         }
147     }
148   return dead;
149 }
150 
nextPlayer()151 void Playerlist::nextPlayer()
152 {
153     debug("nextPlayer()");
154 
155     iterator it;
156 
157     if (!d_activeplayer)
158       it = begin();
159     else
160     {
161         for (it = begin(); it != end(); ++it)
162         {
163             if ((*it) == d_activeplayer)
164             {
165                 it++;
166                 break;
167             }
168         }
169     }
170 
171     // in case we have got a dead player, continue iterating. This breaks
172     // if we have ONLY dead players which we assume never happens.
173     while ((it == end()) || ((*it)->isDead()))
174     {
175         if (it == end())
176         {
177             it = begin();
178             continue;
179         }
180         it++;
181     }
182 
183     d_activeplayer = (*it);
184     updateViewingPlayer();
185     debug("got player: " <<d_activeplayer->getName())
186 }
187 
getPlayer(Glib::ustring name) const188 Player* Playerlist::getPlayer(Glib::ustring name) const
189 {
190     debug("getPlayer()");
191     for (const_iterator it = begin(); it != end(); ++it)
192       if ((*it)->getName() == name) return (*it);
193     return 0;
194 }
195 
getPlayer(guint32 id) const196 Player* Playerlist::getPlayer(guint32 id) const
197 {
198   IdMap::const_iterator it = d_id.find(id);
199   if (it == d_id.end())
200     return NULL;
201   return (*it).second;
202 }
203 
getNoOfPlayers() const204 guint32 Playerlist::getNoOfPlayers() const
205 {
206     unsigned int number = 0;
207 
208     for (const_iterator it = begin(); it != end(); it++)
209     {
210         if (((*it) != d_neutral) && !(*it)->isDead())
211             number++;
212     }
213 
214     return number;
215 }
216 
getFirstLiving() const217 Player* Playerlist::getFirstLiving() const
218 {
219     for (const_iterator it = begin(); ; it++)
220         if (!(*it)->isDead() && *it != d_neutral)
221             return (*it);
222 }
223 
save(XML_Helper * helper) const224 bool Playerlist::save(XML_Helper* helper) const
225 {
226     //to prevent segfaults
227     if (!d_activeplayer)
228         d_activeplayer = (*begin());
229 
230     bool retval = true;
231 
232     retval &= helper->openTag(Playerlist::d_tag);
233     retval &= helper->saveData("active", d_activeplayer->getId());
234     retval &= helper->saveData("neutral", d_neutral->getId());
235 
236     for (const_iterator it = begin(); it != end(); it++)
237         retval &= (*it)->save(helper);
238 
239     retval &= helper->closeTag();
240 
241     return retval;
242 }
243 
add(Player * player)244 void Playerlist::add(Player *player)
245 {
246   push_back(player);
247   d_id[player->getId()] = player;
248 }
249 
load(Glib::ustring tag,XML_Helper * helper)250 bool Playerlist::load(Glib::ustring tag, XML_Helper* helper)
251 {
252     static guint32 active = 0;
253     static guint32 neutral = 0;
254 
255     if (tag == Playerlist::d_tag) //only called in the constructor
256     {
257         helper->getData(active, "active");
258         helper->getData(neutral, "neutral");
259         return true;
260     }
261 
262     if (tag != Player::d_tag)
263         return false;
264 
265     Player* p = Player::loadPlayer(helper);
266     if(p == 0)
267         return false;
268 
269     //insert player...
270     add(p);
271 
272     //set neutral and active
273     if (p->getId() == neutral)
274       d_neutral = p;
275     if (p->getId() == active)
276       d_activeplayer = p;
277 
278     updateViewingPlayer();
279 
280     return true;
281 }
282 
flErase(Playerlist::iterator it)283 Playerlist::iterator Playerlist::flErase(Playerlist::iterator it)
284 {
285     if ((*it) == d_neutral)
286         d_neutral = 0;
287 
288     delete (*it);
289     return erase (it);
290 }
291 
compareDiplomaticScores(const struct rankable_t lhs,const struct rankable_t rhs)292 bool compareDiplomaticScores (const struct rankable_t lhs,
293 			      const struct rankable_t rhs)
294 {
295   /* make ties prefer normal player order */
296   if (lhs.score == rhs.score)
297     return lhs.player->getId() > rhs.player->getId();
298   else
299     return lhs.score < rhs.score;
300 }
301 
get_title(int rank)302 Glib::ustring Playerlist::get_title(int rank)
303 {
304   if (rank == 0)
305     return _("Statesman");
306   else if (rank == 1)
307     return _("Diplomat");
308   else if (rank == 2)
309     return _("Pragmatist");
310   else if (rank == 3)
311     return _("Politician");
312   else if (rank == 4)
313     return _("Deceiver");
314   else if (rank == 5)
315     return _("Scoundrel");
316   else if (rank == 6)
317     return _("Turncoat");
318   else if (rank == 7)
319     return _("Running Dog");
320   return _("unknown");
321 }
322 
calculateDiplomaticRankings()323 void Playerlist::calculateDiplomaticRankings()
324 {
325   unsigned int i = 0;
326   int used_titles[MAX_PLAYERS];
327   memset (used_titles, 0, sizeof (used_titles));
328 
329   //determine the rank for each player
330   //add up the scores for all living players, and sort
331   std::list<struct rankable_t> rankables;
332   for (iterator pit = begin (); pit != end (); pit++)
333     {
334       if ((*pit) == d_neutral)
335 	continue;
336       if ((*pit)->isDead () == true)
337 	continue;
338       struct rankable_t rankable;
339       rankable.score = 0;
340       for (iterator it = begin (); it != end (); it++)
341 	{
342 	  if ((*it) == d_neutral)
343 	    continue;
344 	  if ((*it)->isDead () == true)
345 	    continue;
346 	  if (*pit == *it)
347 	    continue;
348 	  rankable.score += (*it)->getDiplomaticScore(*pit);
349 	}
350       rankable.player = *pit;
351       rankables.push_back(rankable);
352     }
353   rankables.sort (compareDiplomaticScores);
354   std::reverse (rankables.begin (), rankables.end ());
355 
356   i = 1;
357   for (std::list<struct rankable_t>::iterator rit = rankables.begin ();
358        rit != rankables.end (); rit++)
359     {
360       (*rit).player->setDiplomaticRank(i);
361       i++;
362     }
363 
364   // given the rankings, what are the titles?
365   // the titles are depleted from the middle as players die.
366   // 7 means deplete first, 0 means deplete last.
367   unsigned int deplete[MAX_PLAYERS] = { 0, 2, 4, 6, 7, 5, 3, 1 };
368 
369   unsigned int numAlive = countPlayersAlive ();
370   // okay, we take the first numAlive titles
371 
372   std::vector<Glib::ustring> available_titles;
373   for (i = numAlive; i < MAX_PLAYERS ; i++)
374     {
375       for (unsigned int j = 0; j < MAX_PLAYERS; j++)
376 	{
377 	  if (deplete[j] == i)
378             used_titles[j] = 1;
379 	}
380     }
381   for (unsigned int j = 0; j < MAX_PLAYERS; j++)
382     {
383       if (used_titles[j] != 1)
384 	available_titles.push_back (get_title(j));
385     }
386 
387   for (const_iterator it = begin (); it != end (); it++)
388     {
389       if ((*it) == d_neutral)
390 	continue;
391       if ((*it)->isDead () == true)
392 	continue;
393       guint32 rank = (*it)->getDiplomaticRank();
394       // recall that the first rank is 1, and not 0.
395       (*it)->setDiplomaticTitle (available_titles[rank - 1]);
396     }
397 
398   return;
399 }
400 
calculateWinners()401 void Playerlist::calculateWinners()
402 {
403     guint32 score;
404     guint32 total_gold = 0;
405     guint32 total_armies = 0;
406     guint32 total_cities = 0;
407     for (const_iterator it = begin(); it != end(); it++)
408       {
409 	if ((*it) == d_neutral)
410 	  continue;
411 	if ((*it)->isDead() == true)
412 	  continue;
413 	total_gold += (*it)->getGold();
414 	total_armies += (*it)->getStacklist()->countArmies();
415       }
416     total_cities = Citylist::getInstance()->size();
417 
418     for (const_iterator it = begin(); it != end(); it++)
419       {
420 	if ((*it) == d_neutral)
421 	  continue;
422 	if ((*it)->isDead() == true)
423 	  continue;
424 
425 	float city_component = (float)
426 	  ((float) Citylist::getInstance()->countCities(*it)/ (float)total_cities) * 70.0;
427 	float gold_component = (float)
428 	  ((float) (*it)->getGold() / (float)total_gold) * 10.0;
429 	float army_component = (float)
430 	  ((float) (*it)->getStacklist()->countArmies() /
431 	   (float)total_armies) * 20.0;
432 	score = (guint32) (city_component + gold_component + army_component);
433         (*it)->reportEndOfRound(score);
434       }
435 
436     return;
437 }
438 
countHumanPlayersAlive() const439 guint32 Playerlist::countHumanPlayersAlive() const
440 {
441   guint32 retval = 0;
442   for (const_iterator it = begin(); it != end(); it++)
443     if ((*it)->isDead() == false && (*it)->getType() == Player::HUMAN)
444       retval++;
445   return retval;
446 }
447 
countPlayersAlive() const448 guint32 Playerlist::countPlayersAlive () const
449 {
450   guint32 numAlive = 0;
451 
452   for (const_iterator it = begin (); it != end (); it++)
453     {
454       if ((*it) == d_neutral)
455 	continue;
456       if ((*it)->isDead () == true)
457 	continue;
458       numAlive++;
459     }
460   return numAlive;
461 }
462 
negotiateDiplomacy()463 void Playerlist::negotiateDiplomacy()
464 {
465   // hold diplomatic talks, and determine diplomatic outcomes
466   for (iterator pit = begin(); pit != end(); pit++)
467     {
468       if ((*pit)->isDead())
469 	continue;
470 
471       if ((*pit) == getNeutral())
472 	continue;
473 
474       for (iterator it = begin(); it != end(); it++)
475 	{
476 
477 	  if ((*it)->isDead())
478 	    continue;
479 
480 	  if ((*it) == getNeutral())
481 	    continue;
482 
483 	  if ((*it) == (*pit))
484 	    break;
485 
486 	  Player::DiplomaticState old_state = (*pit)->getDiplomaticState(*it);
487 	  Player::DiplomaticState new_state = (*pit)->negotiateDiplomacy(*it);
488 	  (*pit)->declareDiplomacy (new_state, (*it), false);
489 	  (*pit)->proposeDiplomacy (Player::NO_PROPOSAL, (*it));
490 	  (*it)->declareDiplomacy (new_state, (*pit), false);
491 	  (*it)->proposeDiplomacy (Player::NO_PROPOSAL, (*pit));
492 	  if (old_state != new_state)
493 	    {
494 	      Player *me = *pit;
495 	      Player *them = *it;
496 	      if (new_state == Player::AT_PEACE)
497 		{
498 		  //their view of me goes up
499 		  them->improveDiplomaticRelationship(me, 1);
500 		  //their allies think better of me
501 		  me->improveAlliesRelationship (them, 1, Player::AT_PEACE);
502 		  //their enemies think less of me
503 		  them->deteriorateAlliesRelationship (me, 1, Player::AT_WAR);
504 		}
505 	      else if (new_state == Player::AT_WAR)
506 		{
507 		  //their view of me goes down
508 		  them->deteriorateDiplomaticRelationship(me, 1);
509 		  //their allies view of me goes down
510 		  them->deteriorateAlliesRelationship(me, 1, Player::AT_PEACE);
511 		  //their enemies view of me goes up
512 		  me->improveAlliesRelationship(them, 1, Player::AT_WAR);
513 		}
514 	    }
515 	}
516     }
517 }
518 
swap(Player * old_player,Player * new_player)519 void Playerlist::swap(Player *old_player, Player *new_player)
520 {
521   std::replace(begin(), end(), old_player, new_player);
522   //point cities to the new owner
523   Citylist::getInstance()->changeOwnership (old_player, new_player);
524   Ruinlist::getInstance()->changeOwnership (old_player, new_player);
525   VectoredUnitlist::getInstance()->changeOwnership (old_player, new_player);
526   AI_Analysis::changeOwnership(old_player, new_player);
527   if (old_player == d_activeplayer)
528     {
529       d_activeplayer = new_player;
530       d_activeplayer->setActivestack(0);
531     }
532   if (old_player == viewingplayer)
533     viewingplayer = new_player;
534   d_id[new_player->getId()] = new_player;
535   GameMap::getInstance()->clearStackPositions();
536   GameMap::getInstance()->updateStackPositions();
537   /* note, we don't have to change the player associated with flag graphics
538      because it's stored as an id. */
539 }
540 
randomly(const Player * lhs,const Player * rhs)541 bool Playerlist::randomly(const Player *lhs, const Player *rhs)
542 {
543   (void) rhs;
544   if (lhs == Playerlist::getInstance()->getNeutral())
545     return false;
546   if (Rnd::rand() % 2 == 0)
547     return true;
548   else
549     return false;
550 }
551 
inOrderOfId(const Player * lhs,const Player * rhs)552 bool Playerlist::inOrderOfId(const Player *lhs, const Player *rhs)
553 {
554   if (lhs->getId() > rhs->getId())
555     return false;
556   else
557     return true;
558 }
559 
560 //randomly reorder the player list, but keeping neutral last.
randomizeOrder()561 void Playerlist::randomizeOrder()
562 {
563   sort(randomly);
564   d_activeplayer = NULL;
565   viewingplayer = NULL;
566 }
567 
nextRound(bool diplomacy,bool * surrender_already_offered)568 void Playerlist::nextRound(bool diplomacy, bool *surrender_already_offered)
569 {
570   // update diplomacy
571   if (diplomacy)
572     {
573       negotiateDiplomacy();
574       calculateDiplomaticRankings();
575     }
576 
577   // update winners
578   calculateWinners();
579 
580   // offer surrender
581   if (countHumanPlayersAlive() == 1 &&
582       *surrender_already_offered == 0)
583     {
584       for (iterator it = begin(); it != end(); it++)
585 	{
586 	  if ((*it)->getType() == Player::HUMAN)
587 	    {
588 	      int target_level = Citylist::getInstance()->size() / 2;
589 	      if (Citylist::getInstance()->countCities(*it) > target_level)
590 		{
591 		  *surrender_already_offered = 1;
592 		  ssurrender.emit(*it);
593 		  break;
594 		}
595 	    }
596 	}
597     }
598 }
599 
syncPlayer(GameParameters::Player player)600 void Playerlist::syncPlayer(GameParameters::Player player)
601 {
602   Player *p = getPlayer((guint32)player.id);
603   if (!p)
604     {
605       //player was off originally, but now it's on
606       guint32 armyset = d_neutral->getArmyset();
607       int width = d_neutral->getFogMap()->getWidth();
608       int height = d_neutral->getFogMap()->getHeight();
609       int gold = d_neutral->getGold();
610       Shieldset *shieldset = GameMap::getShieldset();
611       switch (player.type)
612 	{
613 	case GameParameters::Player::HUMAN:
614 	  p = new RealPlayer(player.name, armyset,
615 			     shieldset->getColor(player.id),
616 			     width, height, Player::HUMAN, player.id);
617 	  break;
618 	case GameParameters::Player::EASY:
619 	  p = new AI_Fast(player.name, armyset,
620 		       	  shieldset->getColor(player.id),
621 			  width, height, player.id);
622 	  break;
623 	case GameParameters::Player::HARD:
624 	  p = new AI_Smart(player.name, armyset,
625 			   shieldset->getColor(player.id),
626 			   width, height, player.id);
627 	  break;
628 	case GameParameters::Player::OFF:
629 	  //was off, now it's still off.
630 	  break;
631 	default:
632           std::cerr << String::ucompose("could not make player with type %1", player.type) << std::endl;
633 	  exit (1);
634 	  break;
635 	}
636       if (p)
637 	{
638 	  p->setGold(gold);
639 	  add(p);
640 
641 	  sort(inOrderOfId);
642 	  d_activeplayer = getFirstLiving();
643           updateViewingPlayer();
644 	}
645       return;
646     }
647   else
648     p->setName(player.name);
649 
650 
651   switch (player.type)
652     {
653     case GameParameters::Player::HUMAN:
654       if (p->getType() != Player::HUMAN)
655 	{
656 	  RealPlayer *new_p = new RealPlayer(*p);
657 	  swap(p, new_p);
658 	}
659       break;
660     case GameParameters::Player::EASY:
661       if (p->getType() != Player::AI_FAST)
662 	{
663 	  AI_Fast *new_p = new AI_Fast(*p);
664 	  swap(p, new_p);
665 	}
666       break;
667     case GameParameters::Player::HARD:
668       if (p->getType() != Player::AI_SMART)
669 	{
670 	  AI_Smart *new_p = new AI_Smart(*p);
671 	  swap(p, new_p);
672 	}
673       break;
674     case GameParameters::Player::OFF:
675 	{
676 	  //point owned cities to neutral
677           Citylist::getInstance()->changeOwnership (p, d_neutral);
678 	  //point owned ruins to neutral
679           Ruinlist::getInstance()->changeOwnership (p, d_neutral);
680           //also copy over the stacks to neutral
681           p->getStacklist()->changeOwnership(p, d_neutral);
682 	  //now get rid of the player entirely
683           GameMap::getInstance()->clearStackPositions();
684           if (d_id.find(p->getId()) != d_id.end())
685             d_id.erase(d_id.find(p->getId()));
686 	  flErase(find(begin(), end(), p));
687           GameMap::getInstance()->updateStackPositions();
688 	}
689       break;
690     default:
691       std::cerr << String::ucompose("could not sync player with type %1", player.type) << std::endl;
692       exit (1);
693       break;
694     }
695 
696   sort(inOrderOfId);
697   d_activeplayer = getFirstLiving();
698   updateViewingPlayer();
699   return;
700 }
701 
syncPlayers(std::vector<GameParameters::Player> players)702 void Playerlist::syncPlayers(std::vector<GameParameters::Player> players)
703 {
704   std::vector<GameParameters::Player>::const_iterator i = players.begin();
705   for (; i != players.end(); i++)
706     syncPlayer(*i);
707 }
708 
turnHumansIntoNetworkPlayers()709 guint32 Playerlist::turnHumansIntoNetworkPlayers()
710 {
711   guint32 count = 0;
712   std::list<Player*> p;
713   for (iterator i = begin(); i != end(); i++)
714     {
715       if ((*i)->getType() == Player::HUMAN)
716 	{
717           count++;
718 	  NetworkPlayer *new_p = new NetworkPlayer(**i);
719           p.push_back(*i);
720 	  swap((*i), new_p);
721 	  i = begin();
722 	  continue;
723 	}
724     }
725   for (std::list<Player*>::iterator j = p.begin(); j != p.end(); j++)
726     delete *j;
727   return count;
728 }
729 
turnHumansInto(Player::Type type,int number_of_players)730 guint32 Playerlist::turnHumansInto(Player::Type type, int number_of_players)
731 {
732   int count = 0;
733   for (iterator i = begin(); i != end(); i++)
734     {
735       if (count >= number_of_players && number_of_players > 0)
736 	break;
737       if ((*i)->getType() == Player::HUMAN)
738 	{
739 	  switch (type)
740 	    {
741 	    case Player::AI_DUMMY:
742 		{
743 		  AI_Dummy *new_p = new AI_Dummy(**i);
744 		  swap((*i), new_p);
745 		  //delete *i; fixme
746 		  i = begin();
747 		  count++;
748 		  continue;
749 		}
750 	      break;
751 	    case Player::AI_FAST:
752 		{
753 		  AI_Fast *new_p = new AI_Fast(**i);
754 		  swap((*i), new_p);
755 		  //delete *i; fixme
756 		  i = begin();
757 		  count++;
758 		  continue;
759 		}
760 	      break;
761 	    case Player::AI_SMART:
762 		{
763 		  AI_Smart *new_p = new AI_Smart(**i);
764 		  swap((*i), new_p);
765 		  //delete *i; fixme
766 		  i = begin();
767 		  count++;
768 		  continue;
769 		}
770 	      break;
771 	    case Player::NETWORKED:
772 		{
773 		  NetworkPlayer *new_p = new NetworkPlayer(**i);
774 		  swap((*i), new_p);
775 		  //delete *i; fixme
776 		  i = begin();
777 		  count++;
778 		  continue;
779 		}
780 	      break;
781 	    case Player::HUMAN:
782 	      break;
783 	    }
784 	}
785     }
786   return count;
787 }
788 
789 std::list<guint32> given_turn_order;
inGivenOrder(const Player * lhs,const Player * rhs)790 bool Playerlist::inGivenOrder(const Player *lhs, const Player *rhs)
791 {
792   if (given_turn_order.size() == 0)
793     return true;
794 
795   int count = 0;
796   for(std::list<guint32>::iterator it = given_turn_order.begin();
797       it != given_turn_order.end(); it++)
798     {
799       count++;
800       if (lhs->getId() == (*it))
801 	break;
802     }
803   int lhs_rank = count;
804   count = 0;
805   for(std::list<guint32>::iterator it = given_turn_order.begin();
806       it != given_turn_order.end(); it++)
807     {
808       count++;
809       if (rhs->getId() == (*it))
810 	break;
811     }
812   int rhs_rank = count;
813   return lhs_rank < rhs_rank;
814 }
815 
reorder(std::list<guint32> order)816 void Playerlist::reorder(std::list<guint32> order)
817 {
818   given_turn_order = order;
819   sort(inGivenOrder);
820   given_turn_order.clear();
821   d_activeplayer = getFirstLiving();
822   updateViewingPlayer();
823 }
824 
getHistoryForHeroId(guint32 id) const825 std::list<History *>Playerlist::getHistoryForHeroId(guint32 id) const
826 {
827   std::list<History*> no_events;
828   for (const_iterator it = begin(); it != end(); ++it)
829     {
830       std::list<History *>events = (*it)->getHistoryForHeroId(id);
831       if (events.size() > 0)
832 	return events;
833     }
834   return no_events;
835 }
836 
surrender()837 void Playerlist::surrender()
838 {
839   //the last human player has accepted surrender
840   for (iterator it = begin(); it != end(); it++)
841     {
842       if ((*it)->getType() != Player::HUMAN)
843         (*it)->setSurrendered(true);
844     }
845 }
846 
isEndOfRound() const847 bool Playerlist::isEndOfRound() const
848 {
849   //check to see if all players have moved this round.
850   //do all players have the same number of history:end_turn events?
851   if (d_activeplayer == NULL)
852     return false;
853   guint32 count = d_activeplayer->countEndTurnHistoryEntries();
854   for (const_iterator it = begin(); it != end(); it++)
855     {
856       if (*it == d_activeplayer)
857 	continue;
858       if (count != (*it)->countEndTurnHistoryEntries())
859 	return false;
860     }
861   return true;
862 }
863 
setWinningPlayer(Player * winner)864 void Playerlist::setWinningPlayer(Player *winner)
865 {
866   //only for humans
867   d_activeplayer = winner;
868 }
869 
getWinningPlayer() const870 Player *Playerlist::getWinningPlayer() const
871 {
872   guint32 best_score = 0;
873   Player *winning_player = NULL;
874   for (const_iterator it = begin(); it != end(); it++)
875     {
876       Player *p = (*it);
877       if (p->isDead() == false)
878         continue;
879       if (p == getNeutral())
880         continue;
881       if (p->getScore() >= best_score)
882         {
883           best_score = p->getScore();
884           winning_player = p;
885         }
886     }
887   return winning_player;
888 }
889 
hasArmyset(guint32 id) const890 bool Playerlist::hasArmyset(guint32 id) const
891 {
892   for (const_iterator it = begin(); it != end(); it++)
893     {
894       if ((*it)->getArmyset() == id)
895         return true;
896     }
897   return false;
898 }
899 
setNewColours(Shieldset * shieldset)900 void Playerlist::setNewColours(Shieldset *shieldset)
901 {
902   for (iterator it = begin(); it != end(); it++)
903     (*it)->setColor(shieldset->getColor((*it)->getId()));
904 }
905 
clearAllActions()906 void Playerlist::clearAllActions()
907 {
908   for (iterator it = begin(); it != end(); it++)
909     (*it)->clearActionlist();
910 }
911 
syncNeutral()912 void Playerlist::syncNeutral()
913 {
914   if (d_neutral == NULL)
915     return;
916   if (d_neutral->getType() == Player::AI_DUMMY)
917     return;
918   //okay, let's sync it.
919   Player *p = new AI_Dummy(*d_neutral);
920   swap(d_neutral, p);
921   d_neutral = p;
922 }
923 
getStackById(guint32 id) const924 Stack *Playerlist::getStackById(guint32 id) const
925 {
926   //this method checks each stacklist for the given stack id.
927   //the stack ids in each stacklist are in a std::map, so that's how the
928   //stack pointers are gotten.
929   for (const_iterator j = begin(), jend = end(); j != jend; ++j)
930     {
931       Stack *s = (*j)->getStacklist()->getStackById(id);
932       if (s)
933         return s;
934     }
935   return NULL;
936 }
937 
updateViewingPlayer()938 void Playerlist::updateViewingPlayer ()
939 {
940   /*
941    * the idea here is that the viewing player is related to the
942    * hidden map.
943    *
944    * imagine a computer player moving and then it walks into the area of
945    * your map that you have uncovered.
946    *
947    * i think the smallmap happens to be getting blanked right now,
948    * but this funciton is about retaining the last human player as the
949    * player who can see movements through his or her territory.
950    *
951    * the blanking of the smallmap/bigmap is because:
952    * it's not really fair to show one player some enemy units going through
953    * his or her territory, and not all players.  why should one player be
954    * rewarded in this way just by fluke?
955    *
956    * this is the story for hotseat anyway.  i'm not sure how it relates to
957    * network play.
958    */
959   if (d_activeplayer && d_activeplayer->getType() == Player::HUMAN)
960     viewingplayer = d_activeplayer;
961   else
962     viewingplayer = getNeutral();
963 }
964 
getTurnOrderNumber(const Player * p)965 guint32 Playerlist::getTurnOrderNumber(const Player *p)
966 {
967   guint32 count = 1;
968   for (const_iterator i = begin(); i != end(); i++)
969     {
970       if ((*i) == p)
971         break;
972       count++;
973     }
974   return count;
975 }
976 
countAllStacks() const977 guint32 Playerlist::countAllStacks () const
978 {
979   guint32 count = 0;
980   for (const_iterator i = begin(); i != end(); i++)
981     count += (*i)->getStacklist ()->size ();
982   return count;
983 }
984 
playerHasNoCapitalCity() const985 bool Playerlist::playerHasNoCapitalCity () const
986 {
987   for (const_iterator i = begin (); i != end (); i++)
988     if (*i != d_neutral &&
989         Citylist::getInstance ()->getCapitalCity (*i) == NULL)
990       return true;
991   return false;
992 }
993