1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl 2 // Copyright (C) 2001, 2002, 2003, 2004, 2005 Ulf Lorenz 3 // Copyright (C) 2007, 2008, 2009, 2014, 2015, 2017, 2020 Ben Asselstine 4 // Copyright (C) 2007 Ole Laursen 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Library General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 // 02110-1301, USA. 20 21 #pragma once 22 #ifndef PLAYERLIST_H 23 #define PLAYERLIST_H 24 25 #include <list> 26 #include <map> 27 #include <vector> 28 #include <sigc++/trackable.h> 29 #include <sigc++/signal.h> 30 #include "game-parameters.h" 31 32 class History; 33 class Shieldset; 34 class Stack; 35 36 #include "player.h" 37 38 //! A list of all of the Player objects in a scenario. 39 /** 40 * The Playerlist is implemented as a singleton class. The currently 41 * active player is designated, you can access players by name or id and the 42 * playerlist can check if there are more than one player remaining alive. 43 * This class also holds methods that affect all players. 44 */ 45 46 class Playerlist : public std::list<Player*>, public sigc::trackable 47 { 48 public: 49 50 //! The xml tag of this object in a saved-game file. 51 static Glib::ustring d_tag; 52 53 // Set Methods 54 55 //! Set the winning human player. 56 void setWinningPlayer(Player *winner); 57 58 //! Set the player who's turn it is. should only be used by the editor. setActiveplayer(Player * p)59 void setActiveplayer(Player *p) {d_activeplayer = p;}; 60 61 //! set the player who is looking at the bigmap and smallmap. 62 //void setViewingplayer(Player *p) {viewingplayer = p;}; 63 64 //! Get Methods 65 66 //! Returns the neutral player. getNeutral()67 Player* getNeutral() const {return d_neutral;} 68 69 //! The game is over and this is the winner. 70 Player *getWinningPlayer() const; 71 72 73 // Methods that operate on the class data and modify the class. 74 75 //! Sets the active player to the next player in the order. 76 void nextPlayer(); 77 78 /** 79 * Checks if a player is alive and has no cities left. If not then 80 * this method marks the player as killed. 81 * 82 * @param Returns whether or not any players were marked as dead. 83 */ 84 //! Kill any players that don't have cities left. 85 bool checkPlayers(); 86 87 /** 88 * Though the neutral player is located in the list of existing 89 * players, it is handled in a special way in many different cases. 90 * 91 * There can only be one neutral player per Playerlist. 92 * 93 * @param neutral The new neutral player. 94 */ 95 //! Set the neutral player. setNeutral(Player * neutral)96 void setNeutral(Player* neutral) {d_neutral = neutral;} 97 98 /** 99 * Swap out a player from the list and replace it with a new one. 100 * Specical care is taken to remove all references to the original 101 * player and replace it with a reference to the new player. 102 * 103 * The purpose of this method is to change a human player into a 104 * computer player and vice-versa. 105 * 106 * @param old_player A pointer to the player to replace. 107 * @param new_player A pointer to the new player to replace the 108 * original player. 109 */ 110 //! Replace a Player in the list with a new Player. 111 void swap(Player *old_player, Player *new_player); 112 113 /** 114 * Erase a Player from the list, and free the contents of the Player. 115 * 116 * @param it The place in the Playerlist to erase. 117 * 118 * @return The place in the list that was erased. 119 */ 120 //! Erase a player from the list. 121 iterator flErase(iterator it); 122 123 /** 124 * This method is called when a round starts. 125 * The purpose of this method is to calculate who is winning, and 126 * it to negotiate diplomacy between players. This method also 127 * implements the computer players collectively surrendering to a 128 * final human player. 129 * 130 * @param diplomacy Whether or not we should negotiate diplomacy 131 * between players. 132 * @param surrender_already_offered Tells the method if surrender 133 * has already been offered by the computer 134 * players. This needs to be kept track of 135 * because the computer players only offer 136 * surrender once. The method will change this 137 * value from false to true if it decided that 138 * the computer players collectively offer 139 * surrender. 140 */ 141 //! Callback method to process all players at the start of a round. 142 void nextRound(bool diplomacy, bool *surrender_already_offered); 143 144 /** 145 * The purpose of randomzing the Playerlist is to implement 146 * random turns. 147 * Note: This method does not set the active player. 148 */ 149 //! Randomize the order of the players in the list. 150 void randomizeOrder(); 151 152 /** 153 * This method takes care of giving a player it's diplomatic 154 * ranking among all other players. The rank is determined by 155 * adding up all of the diplomatic scores, and then sorting them. 156 * Each rank has a title. There is always a Player who has the 157 * title of `Statesman', and there is always a Player who has the 158 * title of `Running Dog'. The other titles disappear as the other 159 * players die off. 160 */ 161 //! Figure out who's winning diplomatically. 162 void calculateDiplomaticRankings(); 163 164 //! Sync the playerlist. 165 /** 166 * Sync the playerlist with the list of players given. 167 */ 168 void syncPlayers(std::vector<GameParameters::Player> players); 169 170 //! Sync the given player with the playerlist 171 void syncPlayer(GameParameters::Player player); 172 173 //! Switch the neutral player to AI_DUMMY if it has any other type. 174 void syncNeutral(); 175 176 //! Converts all of the human players into network players. 177 guint32 turnHumansIntoNetworkPlayers(); 178 179 //! Converts a given number of the human players into a type of player. 180 guint32 turnHumansInto(Player::Type type, int num_players = -1); 181 182 //! Reorder the list according to the given order. 183 void reorder(std::list<guint32> order); 184 185 //! Perform the surrender of all computer players. 186 void surrender(); 187 188 //! Add a player to the list. Use this instead of push_back. 189 void add(Player *player); 190 191 //! Reassign player colours. 192 void setNewColours(Shieldset *shieldset); 193 194 //! Remove all actions from every player's action list. 195 void clearAllActions(); 196 197 // Methods that operate on the class data but do not modify it. 198 199 /** 200 * Scan the list of players for a Player with a given name. 201 * 202 * @param name The name of the Player to lookup. 203 * 204 * @return A pointer to the Player if it is found, or NULL if it isn't. 205 */ 206 //! Lookup a Player by it's name. 207 Player* getPlayer(Glib::ustring name) const; 208 209 /** 210 * Scan the list of players for a Player with a given Id. 211 * 212 * @param id The id of the Player to lookup. 213 * 214 * @return A pointer to the Player if it is found, or NULL if it isn't. 215 */ 216 //! Lookup a Player by it's Id. 217 Player* getPlayer(guint32 id) const; 218 219 //! Returns the number of living players (neutral player excluded.) 220 guint32 getNoOfPlayers() const; 221 222 /** 223 * Scan the list of players for the first Player that is alive. 224 * This method is used to determine the beginning of a round. 225 * 226 * @return A pointer to the first living Player. 227 */ 228 //! Return the first living Player in the list. 229 Player* getFirstLiving() const; 230 231 //! Saves the playerlist to an opened saved-game file. 232 bool save(XML_Helper* helper) const; 233 234 //! Return the number of human players left alive in the list. 235 guint32 countHumanPlayersAlive() const; 236 237 //! Return the number of players left alive, not including neutral. 238 guint32 countPlayersAlive() const; 239 240 //! Return the total number of stacks on the map. 241 guint32 countAllStacks () const; 242 243 //! Return true if one non-neutral player doesn't have a capital city. 244 bool playerHasNoCapitalCity () const; 245 246 //! Return the list of activities that the given hero has accomplished. 247 std::list<History *>getHistoryForHeroId(guint32 id) const; 248 249 //! Return a stack belonging to any player with the given id. 250 Stack *getStackById(guint32 id) const; 251 252 /** 253 \brief Check to see if this is the end of the round or not. 254 */ 255 bool isEndOfRound() const; 256 257 //! Return true if any of the players use the given armyset. 258 bool hasArmyset(guint32 id) const; 259 260 //! Get which numeric sequence the player is in this round 261 guint32 getTurnOrderNumber(const Player *p); 262 // Signals 263 264 /** 265 * @param player The player who has died. 266 */ 267 //! Emitted when a player has died. 268 sigc::signal<void, Player*> splayerDead; 269 270 /** 271 * Emitted when the computer players collectively offer surrender to 272 * a single remaining human player. 273 * 274 * @param player The human player who is being surrendered to. 275 */ 276 //! Emitted when a surrender is offered. 277 sigc::signal<void, Player*> ssurrender; 278 279 280 // Static Methods 281 282 //! Gets the singleton instance or creates a new one. 283 static Playerlist* getInstance(); 284 285 /** 286 * Load all Players in the Playerlist from a saved-game file. 287 * 288 * @param helper The opened saved-game file to read from. 289 * 290 * @return The loaded Playerlist. 291 */ 292 //! Loads the playerlist from a saved-game file. 293 static Playerlist* getInstance(XML_Helper* helper); 294 295 //! Explicitly deletes the singleton instance. 296 static void deleteInstance(); 297 298 //! Returns the active player (the Player whose turn it is). getActiveplayer()299 static Player* getActiveplayer() {return d_activeplayer;} 300 301 //! Returns the viewing player (the Player who is looking at maps). getViewingplayer()302 static Player *getViewingplayer() {return viewingplayer;} 303 304 protected: 305 306 //! Default constructor. 307 Playerlist(); 308 309 //! Loading constructor. 310 Playerlist(XML_Helper* helper); 311 312 //! Destructor. 313 ~Playerlist(); 314 315 private: 316 //! Callback for loading the playerlist from an opened saved-game file. 317 bool load(Glib::ustring, XML_Helper* helper); 318 319 //! Comparison function to assist in sorting the list of players. 320 static bool randomly(const Player *lhs, const Player *rhs); 321 322 //! Comparison function to assist in sorting the list of players. 323 static bool inGivenOrder(const Player *lhs, const Player *rhs); 324 325 //! Comparison function to assist in sorting the list of players. 326 static bool inOrderOfId(const Player *lhs, const Player *rhs); 327 328 //! Calculate new scores for all players. 329 void calculateWinners(); 330 331 //! Calculate new diplomatic states for all players. 332 void negotiateDiplomacy(); 333 334 void updateViewingPlayer (); 335 336 Glib::ustring get_title(int rank); 337 // DATA 338 339 //! The pointer to the player whose turn it is in the list. 340 static Player* d_activeplayer; 341 342 //! The player that the smallmap and bigmap are being viewed as. 343 static Player *viewingplayer; 344 345 //! The pointer to the neutral player in the list. 346 Player* d_neutral; 347 348 typedef std::map<guint32, Player*> IdMap; 349 IdMap d_id; 350 351 //! A static pointer for the singleton instance. 352 static Playerlist* s_instance; 353 354 }; 355 356 //! A helper struct in Playerlist to help with sorting Player objects by score. 357 struct rankable_t 358 { 359 guint32 score; 360 Player *player; 361 }; 362 363 bool compareDiplomaticScores (const struct rankable_t lhs, const struct rankable_t rhs); 364 #endif // PLAYERLIST_H 365