diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index c32f52ad8b..1bf72f8059 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -193,7 +193,7 @@ void AI_RunGameLoop() const Player* p; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->is_ai) { + if (p->is_ai) { /* This should always be true, else something went wrong... */ assert(_ai_player[p->index].active); @@ -249,6 +249,6 @@ void AI_Uninitialize() const Player* p; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->is_ai) AI_PlayerDied(p->index); + if (p->is_ai) AI_PlayerDied(p->index); } } diff --git a/src/ai/default/default.cpp b/src/ai/default/default.cpp index 1e5fcbcb8a..db91cdab35 100644 --- a/src/ai/default/default.cpp +++ b/src/ai/default/default.cpp @@ -3897,8 +3897,7 @@ static void AiHandleTakeover(Player *p) // Ask the guy with the highest performance hist. FOR_ALL_PLAYERS(pp) { - if (pp->is_active && - !(asked & 1) && + if (!(asked & 1) && pp->bankrupt_asked == 0 && best_val < pp->old_economy[1].performance_history) { best_val = pp->old_economy[1].performance_history; diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 06f23acec2..2592b4e742 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -20,6 +20,7 @@ #include "order_func.h" #include "station_type.h" #include "tilehighlight_func.h" +#include "player_base.h" #include "table/sprites.h" #include "table/strings.h" diff --git a/src/autoslope.h b/src/autoslope.h index 025ed1347a..9b5766c097 100644 --- a/src/autoslope.h +++ b/src/autoslope.h @@ -39,7 +39,7 @@ static inline bool AutoslopeCheckForEntranceEdge(TileIndex tile, uint z_new, Slo static inline bool AutoslopeEnabled() { return (_settings_game.construction.autoslope && - ((IsValidPlayerID(_current_player) && !_is_old_ai_player) || + ((_current_player < MAX_PLAYERS && !_is_old_ai_player) || (_current_player == OWNER_NONE && _game_mode == GM_EDITOR))); } diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 1d4ca80cb6..482f4bc41c 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -44,8 +44,8 @@ static int32 ClickMoneyCheat(int32 p1, int32 p2) */ static int32 ClickChangePlayerCheat(int32 p1, int32 p2) { - while (IsValidPlayerID((PlayerID)p1)) { - if (_players[p1].is_active) { + while ((uint)p1 < GetPlayerPoolSize()) { + if (IsValidPlayerID((PlayerID)p1)) { SetLocalPlayer((PlayerID)p1); MarkWholeScreenDirty(); diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index c3203c6378..c73c76468f 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -594,7 +594,6 @@ DEF_CONSOLE_CMD(ConKick) DEF_CONSOLE_CMD(ConResetCompany) { - const Player *p; PlayerID index; if (argc == 0) { @@ -613,12 +612,7 @@ DEF_CONSOLE_CMD(ConResetCompany) return true; } - /* Check if company does exist */ - p = GetPlayer(index); - if (!p->is_active) { - IConsoleError("Company does not exist."); - return true; - } + const Player *p = GetPlayer(index); if (p->is_ai) { IConsoleError("Company is owned by an AI."); @@ -1157,8 +1151,6 @@ DEF_CONSOLE_CMD(ConPlayers) FOR_ALL_PLAYERS(p) { char buffer[512]; - if (!p->is_active) continue; - const NetworkPlayerInfo *npi = &_network_player_info[p->index]; GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer)); @@ -1185,7 +1177,7 @@ DEF_CONSOLE_CMD(ConSayPlayer) if (argc != 3) return false; PlayerID player_id = (PlayerID)(atoi(argv[1]) - 1); - if (!IsValidPlayerID(player_id) || !GetPlayer(player_id)->is_active) { + if (!IsValidPlayerID(player_id)) { IConsolePrintF(CC_DEFAULT, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS); return true; } diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp index 717f2c5eb7..bd059212c5 100644 --- a/src/core/enum_type.hpp +++ b/src/core/enum_type.hpp @@ -94,7 +94,15 @@ struct TinyEnumT /** Assignment operator (from Tenum_t type) */ FORCEINLINE TinyEnumT& operator = (enum_type e) { - m_val = (storage_type)e; return *this; + m_val = (storage_type)e; + return *this; + } + + /** Assignment operator (from Tenum_t type) */ + FORCEINLINE TinyEnumT& operator = (uint u) + { + m_val = (storage_type)u; + return *this; } /** postfix ++ operator on tiny type */ diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 093914e395..e540a40bb7 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -21,6 +21,7 @@ #include "player_func.h" #include "slope_func.h" #include "tilehighlight_func.h" +#include "player_base.h" #include "table/sprites.h" #include "table/strings.h" diff --git a/src/economy.cpp b/src/economy.cpp index c5fb839a98..9983ecfaf1 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -292,7 +292,6 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player) /* See if the old_player had shares in other companies */ _current_player = old_player; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; for (i = 0; i < 4; i++) { if (p->share_owners[i] == old_player) { /* Sell his shares */ @@ -565,10 +564,11 @@ static void PlayersCheckBankrupt(Player *p) /* Remove the player */ ChangeOwnershipOfPlayerItems(p->index, PLAYER_SPECTATOR); /* Register the player as not-active */ - p->is_active = false; if (!IsHumanPlayer(p->index) && (!_networking || _network_server) && _ai.enabled) AI_PlayerDied(p->index); + + delete p; } } } @@ -588,18 +588,16 @@ static void PlayersGenStatistics() return; FOR_ALL_PLAYERS(p) { - if (p->is_active) { - memmove(&p->old_economy[1], &p->old_economy[0], sizeof(p->old_economy) - sizeof(p->old_economy[0])); - p->old_economy[0] = p->cur_economy; - memset(&p->cur_economy, 0, sizeof(p->cur_economy)); + memmove(&p->old_economy[1], &p->old_economy[0], sizeof(p->old_economy) - sizeof(p->old_economy[0])); + p->old_economy[0] = p->cur_economy; + memset(&p->cur_economy, 0, sizeof(p->cur_economy)); - if (p->num_valid_stat_ent != 24) p->num_valid_stat_ent++; + if (p->num_valid_stat_ent != 24) p->num_valid_stat_ent++; - UpdateCompanyRatingAndValue(p, true); - PlayersCheckBankrupt(p); + UpdateCompanyRatingAndValue(p, true); + PlayersCheckBankrupt(p); - if (p->block_preview != 0) p->block_preview--; - } + if (p->block_preview != 0) p->block_preview--; } InvalidateWindow(WC_INCOME_GRAPH, 0); @@ -678,8 +676,6 @@ static void PlayersPayInterest() int interest = _economy.interest_rate * 54; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; - _current_player = p->index; SubtractMoneyFromPlayer(CommandCost(EXPENSES_LOAN_INT, (Money)BigMulSU(p->current_loan, interest, 16))); @@ -1767,13 +1763,13 @@ static void DoAcquireCompany(Player *p) } _current_player = old_player; - p->is_active = false; - DeletePlayerWindows(pi); InvalidateWindowClassesData(WC_TRAINS_LIST, 0); InvalidateWindowClassesData(WC_SHIPS_LIST, 0); InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); + + delete p; } extern int GetAmountOwnedBy(const Player *p, PlayerID owner); @@ -1786,17 +1782,13 @@ extern int GetAmountOwnedBy(const Player *p, PlayerID owner); */ CommandCost CmdBuyShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Player *p; CommandCost cost(EXPENSES_OTHER); /* Check if buying shares is allowed (protection against modified clients) */ /* Cannot buy own shares */ if (!IsValidPlayerID((PlayerID)p1) || !_settings_game.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; - p = GetPlayer((PlayerID)p1); - - /* Cannot buy shares of non-existent nor bankrupted company */ - if (!p->is_active) return CMD_ERROR; + Player *p = GetPlayer((PlayerID)p1); /* Protect new companies from hostile takeovers */ if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_PROTECTED); @@ -1835,23 +1827,17 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 */ CommandCost CmdSellShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Player *p; - Money cost; - /* Check if selling shares is allowed (protection against modified clients) */ /* Cannot sell own shares */ if (!IsValidPlayerID((PlayerID)p1) || !_settings_game.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; - p = GetPlayer((PlayerID)p1); - - /* Cannot sell shares of non-existent nor bankrupted company */ - if (!p->is_active) return CMD_ERROR; + Player *p = GetPlayer((PlayerID)p1); /* Those lines are here for network-protection (clients can be slow) */ if (GetAmountOwnedBy(p, _current_player) == 0) return CommandCost(); /* adjust it a little to make it less profitable to sell and buy */ - cost = CalculateCompanyValue(p) >> 2; + Money cost = CalculateCompanyValue(p) >> 2; cost = -(cost - (cost >> 7)); if (flags & DC_EXEC) { @@ -1874,7 +1860,6 @@ CommandCost CmdSellShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint3 */ CommandCost CmdBuyCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Player *p; PlayerID pid = (PlayerID)p1; /* Disable takeovers in multiplayer games */ @@ -1883,7 +1868,7 @@ CommandCost CmdBuyCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) /* Do not allow players to take over themselves */ if (pid == _current_player) return CMD_ERROR; - p = GetPlayer(pid); + Player *p = GetPlayer(pid); if (!p->is_ai) return CMD_ERROR; diff --git a/src/engine.cpp b/src/engine.cpp index 71e09773b0..6712860f3f 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -313,7 +313,7 @@ static PlayerID GetBestPlayer(uint8 pp) best_hist = -1; best_player = PLAYER_SPECTATOR; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->block_preview == 0 && !HasBit(mask, p->index) && + if (p->block_preview == 0 && !HasBit(mask, p->index) && p->old_economy[0].performance_history > best_hist) { best_hist = p->old_economy[0].performance_history; best_player = p->index; @@ -428,14 +428,10 @@ static void NewVehicleAvailable(Engine *e) /* maybe make another rail type available */ RailType railtype = e->u.rail.railtype; assert(railtype < RAILTYPE_END); - FOR_ALL_PLAYERS(p) { - if (p->is_active) SetBit(p->avail_railtypes, railtype); - } + FOR_ALL_PLAYERS(p) SetBit(p->avail_railtypes, railtype); } else if (e->type == VEH_ROAD) { /* maybe make another road type available */ - FOR_ALL_PLAYERS(p) { - if (p->is_active) SetBit(p->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD); - } + FOR_ALL_PLAYERS(p) SetBit(p->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD); } SetDParam(0, GetEngineCategoryName(index)); diff --git a/src/genworld.cpp b/src/genworld.cpp index 05e61b44a3..dcbe15dbc8 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -145,7 +145,7 @@ static void _GenerateWorld(void *arg) } ResetObjectToPlace(); - SetLocalPlayer(_gw.lp); + _local_player = _gw.lp; SetGeneratingWorldProgress(GWP_GAME_START, 1); /* Call any callback */ diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 41a71ef5fd..2c31abf900 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -45,20 +45,17 @@ struct GraphLegendWindow : Window { virtual void OnPaint() { - const Player *p; + for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) { + if (IsValidPlayerID(p)) continue; - FOR_ALL_PLAYERS(p) { - if (p->is_active) continue; - - SetBit(_legend_excluded_players, p->index); - this->RaiseWidget(p->index + 3); + SetBit(_legend_excluded_players, p); + this->RaiseWidget(p + 3); } this->DrawWidgets(); + const Player *p; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; - DrawPlayerIcon(p->index, 4, 18 + p->index * 12); SetDParam(0, p->index); @@ -360,16 +357,16 @@ public: uint excluded_players = _legend_excluded_players; /* Exclude the players which aren't valid */ - const Player* p; - FOR_ALL_PLAYERS(p) { - if (!p->is_active) SetBit(excluded_players, p->index); + for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) { + if (!IsValidPlayerID(p)) SetBit(excluded_players, p); } this->excluded_data = excluded_players; this->num_vert_lines = 24; byte nums = 0; + const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active) nums = max(nums, p->num_valid_stat_ent); + nums = max(nums, p->num_valid_stat_ent); } this->num_on_x_axis = min(nums, 24); @@ -384,8 +381,9 @@ public: this->month = mo; int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { + for (PlayerID k = PLAYER_FIRST; k < MAX_PLAYERS; k++) { + if (IsValidPlayerID(k)) { + p = GetPlayer(k); this->colors[numd] = _colour_gradient[p->player_color][6]; for (int j = this->num_on_x_axis, i = 0; --j >= 0;) { this->cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(p, j); @@ -774,9 +772,7 @@ private: const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active) { - *this->players.Append() = p; - } + *this->players.Append() = p; } this->players.Compact(); @@ -867,7 +863,7 @@ struct PerformanceRatingDetailWindow : Window { { /* Disable the players who are not active */ for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) { - this->SetWidgetDisabledState(i + 13, !GetPlayer(i)->is_active); + this->SetWidgetDisabledState(i + 13, !IsValidPlayerID(i)); } this->UpdatePlayerStats(); @@ -883,7 +879,7 @@ struct PerformanceRatingDetailWindow : Window { * (this is because _score_info is not saved to a savegame) */ Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active) UpdateCompanyRatingAndValue(p, false); + UpdateCompanyRatingAndValue(p, false); } this->timeout = DAY_TICKS * 5; @@ -901,7 +897,7 @@ struct PerformanceRatingDetailWindow : Window { this->DrawWidgets(); /* Check if the currently selected player is still active. */ - if (player == INVALID_PLAYER || !GetPlayer(player)->is_active) { + if (player == INVALID_PLAYER || !IsValidPlayerID(player)) { if (player != INVALID_PLAYER) { /* Raise and disable the widget for the previous selection. */ this->RaiseWidget(player + 13); @@ -912,7 +908,7 @@ struct PerformanceRatingDetailWindow : Window { } for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) { - if (GetPlayer(i)->is_active) { + if (IsValidPlayerID(i)) { /* Lower the widget corresponding to this player. */ this->LowerWidget(i + 13); this->SetDirty(); @@ -928,7 +924,7 @@ struct PerformanceRatingDetailWindow : Window { /* Paint the player icons */ for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) { - if (!GetPlayer(i)->is_active) { + if (!IsValidPlayerID(i)) { /* Check if we have the player as an active player */ if (!this->IsWidgetDisabled(i + 13)) { /* Bah, player gone :( */ diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index a5f853f137..5195c543ba 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -28,6 +28,7 @@ #include "string_func.h" #include "sortlist_type.h" #include "widgets/dropdown_func.h" +#include "player_base.h" #include "table/strings.h" #include "table/sprites.h" diff --git a/src/misc.cpp b/src/misc.cpp index f89f233c52..3e89366b94 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -100,8 +100,8 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date) InitializeTrains(); InitializeNPF(); - AI_Initialize(); InitializePlayers(); + AI_Initialize(); InitializeCheats(); InitTextEffects(); diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index c8408ee859..847200c490 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -69,7 +69,7 @@ CommandCost CmdSetPlayerColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 if (scheme == LS_DEFAULT && state == 0) { const Player *pp; FOR_ALL_PLAYERS(pp) { - if (pp->is_active && pp != p && pp->player_color == colour) return CMD_ERROR; + if (pp != p && pp->player_color == colour) return CMD_ERROR; } } @@ -208,7 +208,6 @@ static bool IsUniqueCompanyName(const char *name) char buf[512]; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; SetDParam(0, p->index); GetString(buf, STR_COMPANY_NAME, lastof(buf)); if (strcmp(buf, name) == 0) return false; @@ -245,7 +244,6 @@ static bool IsUniquePresidentName(const char *name) char buf[512]; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; SetDParam(0, p->index); GetString(buf, STR_PLAYER_NAME, lastof(buf)); if (strcmp(buf, name) == 0) return false; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e8ff55fdf8..f9d45e265c 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -45,6 +45,7 @@ #include "rail_gui.h" #include "tilehighlight_func.h" #include "querystring_gui.h" +#include "player_base.h" #include "table/sprites.h" #include "table/strings.h" diff --git a/src/network/network.cpp b/src/network/network.cpp index e824f44068..7a0cb2ce06 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -40,6 +40,7 @@ #include "../core/alloc_func.hpp" #endif /* DEBUG_DUMP_COMMANDS */ #include "table/strings.h" +#include "../player_base.h" bool _network_server; ///< network-server is active bool _network_available; ///< is network mode available? diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 5a3c7dab6d..cc8e746f55 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -624,9 +624,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) /* New company/spectator (invalid player) or company we want to join is not active * Switch local player to spectator and await the server's judgement */ - if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayerID(_network_playas) || - !GetPlayer(_network_playas)->is_active) { - + if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayerID(_network_playas)) { SetLocalPlayer(PLAYER_SPECTATOR); if (_network_playas != PLAYER_SPECTATOR) { diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index e238b94e26..84ce21e0a3 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -31,6 +31,7 @@ #include "../widgets/dropdown_func.h" #include "../querystring_gui.h" #include "../sortlist_type.h" +#include "../player_base.h" #include "table/strings.h" #include "../table/sprites.h" diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 21c1798772..986b56784d 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -89,8 +89,6 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO) NetworkPopulateCompanyInfo(); FOR_ALL_PLAYERS(player) { - if (!player->is_active) continue; - p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO); p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION); @@ -1299,12 +1297,9 @@ void NetworkPopulateCompanyInfo() uint i; uint16 months_empty; - FOR_ALL_PLAYERS(p) { - if (!p->is_active) { - memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo)); - continue; - } + memset(_network_player_info, 0, sizeof(_network_player_info)); + FOR_ALL_PLAYERS(p) { // Clean the info but not the password ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password)); months_empty = _network_player_info[p->index].months_empty; @@ -1436,7 +1431,7 @@ static void NetworkAutoCleanCompanies() /* Go through all the comapnies */ FOR_ALL_PLAYERS(p) { /* Skip the non-active once */ - if (!p->is_active || p->is_ai) continue; + if (p->is_ai) continue; if (!clients_in_company[p->index]) { /* The company is empty for one month more */ diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 1a85d3d98e..a89e0e5ca7 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -124,9 +124,6 @@ DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO) byte current = 0; /* Go through all the players */ FOR_ALL_PLAYERS(player) { - /* Skip non-active players */ - if (!player->is_active) continue; - current++; /* Send the information */ diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index bef7b37979..146a216828 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -23,6 +23,7 @@ #include "player_func.h" #include "animated_tile_func.h" #include "date_func.h" +#include "player_base.h" #include "table/strings.h" #include "table/sprites.h" diff --git a/src/oldloader.cpp b/src/oldloader.cpp index 90ec6ef792..9175ababe6 100644 --- a/src/oldloader.cpp +++ b/src/oldloader.cpp @@ -1001,14 +1001,14 @@ static const OldChunks player_chunk[] = { static bool LoadOldPlayer(LoadgameState *ls, int num) { - Player *p = GetPlayer((PlayerID)num); + Player *p = new (num) Player(); _current_player_id = (PlayerID)num; if (!LoadChunk(ls, p, player_chunk)) return false; if (_old_string_id == 0) { - p->is_active = false; + delete p; return true; } diff --git a/src/openttd.cpp b/src/openttd.cpp index 9e0b7387cd..2af09b080f 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -302,6 +302,7 @@ static void InitializeDynamicVariables() /* Dynamic stuff needs to be initialized somewhere... */ _industry_mngr.ResetMapping(); _industile_mngr.ResetMapping(); + _Player_pool.AddBlockToPool(); } @@ -335,6 +336,7 @@ static void ShutdownGame() _Group_pool.CleanPool(); _CargoPacket_pool.CleanPool(); _Engine_pool.CleanPool(); + _Player_pool.CleanPool(); free(_config_file); @@ -524,9 +526,6 @@ int ttd_main(int argc, char *argv[]) /* initialize all variables that are allocated dynamically */ InitializeDynamicVariables(); - /* start the AI */ - AI_Initialize(); - /* Sample catalogue */ DEBUG(misc, 1, "Loading sound effects..."); MxInitialize(11025); @@ -1165,16 +1164,6 @@ static void ConvertTownOwner() } } -/* before savegame version 4, the name of the company determined if it existed */ -static void CheckIsPlayerActive() -{ - Player *p; - - FOR_ALL_PLAYERS(p) { - if (p->name_1 != 0) p->is_active = true; - } -} - /* since savegame version 4.1, exclusive transport rights are stored at towns */ static void UpdateExclusiveRights() { @@ -1404,10 +1393,6 @@ bool AfterLoadGame() return false; } - /* in version 4.1 of the savegame, is_active was introduced to determine - * if a player does exist, rather then checking name_1 */ - if (CheckSavegameVersionOldStyle(4, 1)) CheckIsPlayerActive(); - /* The void tiles on the southern border used to belong to a wrong class (pre 4.3). * This problem appears in savegame version 21 too, see r3455. But after loading the * savegame and saving again, the buggy map array could be converted to new savegame @@ -1418,7 +1403,7 @@ bool AfterLoadGame() * a player does not exist yet. So create one here. * 1 exeption: network-games. Those can have 0 players * But this exeption is not true for non dedicated network_servers! */ - if (!_players[0].is_active && (!_networking || (_networking && _network_server && !_network_dedicated))) + if (!IsValidPlayerID(PLAYER_FIRST) && (!_networking || (_networking && _network_server && !_network_dedicated))) DoStartupNewPlayer(false); if (CheckSavegameVersion(72)) { @@ -2316,14 +2301,10 @@ bool AfterLoadGame() * (caused by cheating players in earlier revisions) */ Player *p; FOR_ALL_PLAYERS(p) { - if (!p->is_active) { - for (uint i = 0; i < 4; i++) { p->share_owners[i] = PLAYER_SPECTATOR; } - } else { - for (uint i = 0; i < 4; i++) { - PlayerID o = p->share_owners[i]; - if (o == PLAYER_SPECTATOR) continue; - if (!IsValidPlayerID(o) || o == p->index || !GetPlayer(o)->is_active) p->share_owners[i] = PLAYER_SPECTATOR; - } + for (uint i = 0; i < 4; i++) { + PlayerID o = p->share_owners[i]; + if (o == PLAYER_SPECTATOR) continue; + if (!IsValidPlayerID(o) || o == p->index) p->share_owners[i] = PLAYER_SPECTATOR; } } } @@ -2374,7 +2355,7 @@ bool AfterLoadGame() if (IsBuoyTile(t) || IsDriveThroughStopTile(t) || IsTileType(t, MP_WATER)) { Owner o = GetTileOwner(t); - if (IsValidPlayerID(o) && !GetPlayer(o)->is_active) { + if (o < MAX_PLAYERS && !IsValidPlayerID(o)) { _current_player = o; ChangeTileOwner(t, o, PLAYER_SPECTATOR); } @@ -2388,11 +2369,11 @@ bool AfterLoadGame() for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { /* update even non-existing road types to update tile owner too */ Owner o = GetRoadOwner(t, rt); - if (IsValidPlayerID(o) && !GetPlayer(o)->is_active) SetRoadOwner(t, rt, OWNER_NONE); + if (o < MAX_PLAYERS && !IsValidPlayerID(o)) SetRoadOwner(t, rt, OWNER_NONE); } if (IsLevelCrossing(t)) { Owner o = GetTileOwner(t); - if (!GetPlayer(o)->is_active) { + if (!IsValidPlayerID(o)) { /* remove leftover rail piece from crossing (from very old savegames) */ _current_player = o; DoCommand(t, 0, GetCrossingRailTrack(t), DC_EXEC | DC_BANKRUPT, CMD_REMOVE_SINGLE_RAIL); diff --git a/src/player_base.h b/src/player_base.h index a5009b490f..6e175d1271 100644 --- a/src/player_base.h +++ b/src/player_base.h @@ -5,6 +5,8 @@ #ifndef PLAYER_BASE_H #define PLAYER_BASE_H +#include "player_type.h" +#include "oldpool.h" #include "road_type.h" #include "rail_type.h" #include "date_type.h" @@ -22,7 +24,12 @@ struct PlayerEconomyEntry { Money company_value; }; -struct Player { +DECLARE_OLD_POOL(Player, Player, 1, MAX_PLAYERS) + +struct Player : PoolItem { + Player(uint16 name_1 = 0, bool is_ai = false); + ~Player(); + uint32 name_2; uint16 name_1; char *name; @@ -42,7 +49,6 @@ struct Player { RailTypes avail_railtypes; RoadTypes avail_roadtypes; byte block_preview; - PlayerByte index; uint32 cargo_types; ///< which cargo types were transported the last year @@ -59,7 +65,6 @@ struct Player { int16 bankrupt_timeout; Money bankrupt_value; - bool is_active; bool is_ai; Money yearly_expenses[3][EXPENSES_END]; @@ -71,8 +76,20 @@ struct Player { int16 engine_renew_months; uint32 engine_renew_money; uint16 *num_engines; ///< caches the number of engines of each type the player owns (no need to save this) + + inline bool IsValid() const { return this->name_1 != 0; } }; +inline bool operator < (PlayerID p, uint u) {return (uint)p < u;} + +static inline bool IsValidPlayerID(PlayerID index) +{ + return index < GetPlayerPoolSize() && GetPlayer(index)->IsValid(); +} + +#define FOR_ALL_PLAYERS_FROM(d, start) for (d = GetPlayer(start); d != NULL; d = (d->index + 1U < GetPlayerPoolSize()) ? GetPlayer(d->index + 1U) : NULL) if (d->IsValid()) +#define FOR_ALL_PLAYERS(d) FOR_ALL_PLAYERS_FROM(d, 0) + struct PlayerMoneyBackup { private: Money backup_yearly_expenses[EXPENSES_END]; @@ -85,27 +102,16 @@ public: void Restore(); }; -extern Player _players[MAX_PLAYERS]; -#define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++) - static inline byte ActivePlayerCount() { const Player *p; byte count = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) count++; - } + FOR_ALL_PLAYERS(p) count++; return count; } -static inline Player *GetPlayer(PlayerID i) -{ - assert(IsInsideBS(i, PLAYER_FIRST, lengthof(_players))); - return &_players[i]; -} - Money CalculateCompanyValue(const Player *p); #endif /* PLAYER_BASE_H */ diff --git a/src/player_func.h b/src/player_func.h index 7c0e9de190..cc55f46615 100644 --- a/src/player_func.h +++ b/src/player_func.h @@ -27,11 +27,6 @@ static inline bool IsLocalPlayer() return _local_player == _current_player; } -static inline bool IsValidPlayerID(PlayerID pi) -{ - return IsInsideBS(pi, PLAYER_FIRST, MAX_PLAYERS); -} - static inline bool IsInteractivePlayer(PlayerID pi) { return pi == _local_player; diff --git a/src/player_gui.cpp b/src/player_gui.cpp index 472865c292..65d3d3bdce 100644 --- a/src/player_gui.cpp +++ b/src/player_gui.cpp @@ -346,7 +346,7 @@ private: if (HasBit(this->sel, LS_DEFAULT) && widget == PLW_WIDGET_PRI_COL_DROPDOWN) { const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->index != _local_player) SetBit(used_colours, p->player_color); + if (p->index != _local_player) SetBit(used_colours, p->player_color); } } diff --git a/src/players.cpp b/src/players.cpp index 14906b98f9..cf1dca3552 100644 --- a/src/players.cpp +++ b/src/players.cpp @@ -38,11 +38,11 @@ #include "rail.h" #include "sprite.h" #include "debug.h" +#include "oldpool_func.h" #include "table/strings.h" #include "table/sprites.h" -Player _players[MAX_PLAYERS]; PlayerByte _local_player; PlayerByte _current_player; /* NOSAVE: can be determined from player structs */ @@ -50,6 +50,25 @@ byte _player_colors[MAX_PLAYERS]; PlayerFace _player_face; ///< for player face storage in openttd.cfg HighScore _highscore_table[5][5]; // 4 difficulty-settings (+ network); top 5 +DEFINE_OLD_POOL_GENERIC(Player, Player) + +Player::Player(uint16 name_1, bool is_ai) : name_1(name_1), is_ai(is_ai) +{ + for (uint j = 0; j < 4; j++) this->share_owners[j] = PLAYER_SPECTATOR; +} + +Player::~Player() +{ + free(this->name); + free(this->president_name); + free(this->num_engines); + + if (CleaningPool()) return; + + DeletePlayerWindows(this->index); + this->name_1 = 0; +} + /** * Sets the local player and updates the patch settings that are set on a * per-company (player) basis to reflect the core's state in the GUI. @@ -425,8 +444,6 @@ static byte GeneratePlayerColour() /* Move the colors that look similar to each player's color to the side */ Player *p; FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; - Colours pcolour = (Colours)p->player_color; for (uint i = 0; i < COLOUR_END; i++) { @@ -471,7 +488,7 @@ restart:; continue; FOR_ALL_PLAYERS(pp) { - if (pp->is_active && p != pp) { + if (p != pp) { SetDParam(0, pp->index); GetString(buffer2, STR_PLAYER_NAME, lastof(buffer2)); if (strcmp(buffer2, buffer) == 0) @@ -482,25 +499,6 @@ restart:; } } -static Player *AllocatePlayer() -{ - Player *p; - /* Find a free slot */ - FOR_ALL_PLAYERS(p) { - if (!p->is_active) { - free(p->name); - free(p->president_name); - PlayerID i = p->index; - memset(p, 0, sizeof(Player)); - memset(&_players_ai[i], 0, sizeof(PlayerAI)); - memset(&_players_ainew[i], 0, sizeof(PlayerAiNew)); - p->index = i; - return p; - } - } - return NULL; -} - void ResetPlayerLivery(Player *p) { for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) { @@ -518,21 +516,20 @@ void ResetPlayerLivery(Player *p) */ Player *DoStartupNewPlayer(bool is_ai) { - Player *p; + Player *p = new Player(STR_SV_UNNAMED, is_ai); - p = AllocatePlayer(); if (p == NULL) return NULL; + memset(&_players_ai[p->index], 0, sizeof(PlayerAI)); + memset(&_players_ainew[p->index], 0, sizeof(PlayerAiNew)); + /* Make a color */ p->player_color = GeneratePlayerColour(); ResetPlayerLivery(p); _player_colors[p->index] = p->player_color; - p->name_1 = STR_SV_UNNAMED; - p->is_active = true; p->player_money = p->current_loan = 100000; - p->is_ai = is_ai; _players_ai[p->index].state = 5; // AIS_WANT_NEW_ROUTE p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = PLAYER_SPECTATOR; @@ -557,7 +554,6 @@ Player *DoStartupNewPlayer(bool is_ai) if (is_ai && (!_networking || _network_server) && _ai.enabled) AI_StartNewAI(p->index); - free(p->num_engines); p->num_engines = CallocT(GetEnginePoolSize()); return p; @@ -577,7 +573,7 @@ static void MaybeStartNewPlayer() /* count number of competitors */ n = 0; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->is_ai) n++; + if (p->is_ai) n++; } /* when there's a lot of computers in game, the probability that a new one starts is lower */ @@ -598,26 +594,25 @@ static void MaybeStartNewPlayer() void InitializePlayers() { - memset(_players, 0, sizeof(_players)); - for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) { - _players[i].index = i; - for (uint j = 0; j < 4; j++) _players[i].share_owners[j] = PLAYER_SPECTATOR; - } + _Player_pool.CleanPool(); + _Player_pool.AddBlockToPool(); _cur_player_tick_index = 0; } void OnTick_Players() { - Player *p; - if (_game_mode == GM_EDITOR) return; - p = GetPlayer((PlayerID)_cur_player_tick_index); - _cur_player_tick_index = (_cur_player_tick_index + 1) % MAX_PLAYERS; - if (p->name_1 != 0) GenerateCompanyName(p); + if (IsValidPlayerID((PlayerID)_cur_player_tick_index)) { + Player *p = GetPlayer((PlayerID)_cur_player_tick_index); + if (p->name_1 != 0) GenerateCompanyName(p); - if (AI_AllowNewAI() && _game_mode != GM_MENU && !--_next_competitor_start) - MaybeStartNewPlayer(); + if (AI_AllowNewAI() && _game_mode != GM_MENU && !--_next_competitor_start) { + MaybeStartNewPlayer(); + } + } + + _cur_player_tick_index = (_cur_player_tick_index + 1) % MAX_PLAYERS; } void PlayersYearlyLoop() @@ -626,11 +621,9 @@ void PlayersYearlyLoop() /* Copy statistics */ FOR_ALL_PLAYERS(p) { - if (p->is_active) { - memmove(&p->yearly_expenses[1], &p->yearly_expenses[0], sizeof(p->yearly_expenses) - sizeof(p->yearly_expenses[0])); - memset(&p->yearly_expenses[0], 0, sizeof(p->yearly_expenses[0])); - InvalidateWindow(WC_FINANCES, p->index); - } + memmove(&p->yearly_expenses[1], &p->yearly_expenses[0], sizeof(p->yearly_expenses) - sizeof(p->yearly_expenses[0])); + memset(&p->yearly_expenses[0], 0, sizeof(p->yearly_expenses[0])); + InvalidateWindow(WC_FINANCES, p->index); } if (_settings_client.gui.show_finances && _local_player != PLAYER_SPECTATOR) { @@ -644,20 +637,6 @@ void PlayersYearlyLoop() } } -static void DeletePlayerStuff(PlayerID pi) -{ - Player *p; - - DeletePlayerWindows(pi); - p = GetPlayer(pi); - p->name_1 = STR_NULL; - p->president_name_1 = STR_NULL; - free(p->name); - free(p->president_name); - p->name = NULL; - p->president_name = NULL; -} - /** Change engine renewal parameters * @param tile unused * @param flags operation to perform @@ -972,7 +951,8 @@ CommandCost CmdPlayerCtrl(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) /* Remove the company */ ChangeOwnershipOfPlayerItems(p->index, PLAYER_SPECTATOR); - p->is_active = false; + + delete p; } } break; @@ -985,7 +965,7 @@ CommandCost CmdPlayerCtrl(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (!(flags & DC_EXEC)) return CMD_ERROR; ChangeOwnershipOfPlayerItems(pid_old, pid_new); - DeletePlayerStuff(pid_old); + delete GetPlayer(pid_old); } break; default: return CMD_ERROR; @@ -1063,7 +1043,7 @@ int8 SaveHighScoreValueNetwork() int8 player = -1; /* Sort all active players with the highest score first */ - FOR_ALL_PLAYERS(p) if (p->is_active) pl[count++] = p; + FOR_ALL_PLAYERS(p) pl[count++] = p; GSortT(pl, count, &HighScoreSorter); @@ -1200,7 +1180,7 @@ static const SaveLoad _player_desc[] = { SLE_CONDARR(Player, yearly_expenses, SLE_INT64, 3 * 13, 2, SL_MAX_VERSION), SLE_CONDVAR(Player, is_ai, SLE_BOOL, 2, SL_MAX_VERSION), - SLE_CONDVAR(Player, is_active, SLE_BOOL, 4, SL_MAX_VERSION), + SLE_CONDNULL(1, 4, 99), /* Engine renewal settings */ SLE_CONDNULL(512, 16, 18), @@ -1281,10 +1261,8 @@ static void Save_PLYR() { Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active) { - SlSetArrayIndex(p->index); - SlAutolength((AutolengthProc*)SaveLoad_PLYR, p); - } + SlSetArrayIndex(p->index); + SlAutolength((AutolengthProc*)SaveLoad_PLYR, p); } } @@ -1292,7 +1270,7 @@ static void Load_PLYR() { int index; while ((index = SlIterateArray()) != -1) { - Player *p = GetPlayer((PlayerID)index); + Player *p = new (index) Player(); SaveLoad_PLYR(p); _player_colors[index] = p->player_color; diff --git a/src/road_gui.cpp b/src/road_gui.cpp index edb4746862..c97eb89222 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -24,6 +24,7 @@ #include "settings_type.h" #include "tunnelbridge.h" #include "tilehighlight_func.h" +#include "player_base.h" #include "table/sprites.h" #include "table/strings.h" diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index db8e8b52f5..dab371e7dd 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -619,10 +619,8 @@ public: /* now fill with the player colors */ FOR_ALL_PLAYERS(p) { - if (p->is_active) { - _owner_colors[p->index] = - _colour_gradient[p->player_color][5] * 0x01010101; - } + _owner_colors[p->index] = + _colour_gradient[p->player_color][5] * 0x01010101; } } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 19b87c68fc..e63be04684 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -26,6 +26,7 @@ #include "widgets/dropdown_func.h" #include "newgrf_cargo.h" #include "string_func.h" +#include "player_base.h" #include "table/strings.h" #include "table/sprites.h" diff --git a/src/strings.cpp b/src/strings.cpp index 4a68ae1768..a823211117 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -959,7 +959,7 @@ static char* FormatString(char* buff, const char* str, const int64* argv, uint c PlayerID player = (PlayerID)GetInt32(&argv); /* Nothing is added for AI or inactive players */ - if (IsHumanPlayer(player) && IsValidPlayerID(player)) { + if (IsValidPlayerID(player) && IsHumanPlayer(player)) { int64 args[1]; args[0] = player + 1; buff = GetStringWithArgs(buff, STR_7002_PLAYER, args, last); diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 6d4b4bfbd0..11e422f2da 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -562,20 +562,19 @@ static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed) /* Set generating_world to true to get instant-green grass after removing * player property. */ _generating_world = true; - /* Delete all players */ - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - ChangeOwnershipOfPlayerItems(p->index, PLAYER_SPECTATOR); - p->is_active = false; - } - } - _generating_world = false; /* Delete all stations owned by a player */ Station *st; FOR_ALL_STATIONS(st) { if (IsValidPlayerID(st->owner)) delete st; } + + /* Delete all players */ + FOR_ALL_PLAYERS(p) { + ChangeOwnershipOfPlayerItems(p->index, PLAYER_SPECTATOR); + delete p; + } + _generating_world = false; } } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 101008e2c4..9f2266b9e5 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -1482,7 +1482,7 @@ static int GetPlayerIndexFromMenu(int index) const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && --index < 0) return p->index; + if (--index < 0) return p->index; } } return -1; @@ -1558,19 +1558,18 @@ struct ToolbarPlayerMenuWindow : Window { sel--; } - const Player *p; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - if (p->index == sel) { + for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) { + if (IsValidPlayerID(p)) { + if (p == sel) { GfxFillRect(x, y, x + 238, y + 9, 0); } - DrawPlayerIcon(p->index, x + 2, y + 1); + DrawPlayerIcon(p, x + 2, y + 1); - SetDParam(0, p->index); - SetDParam(1, p->index); + SetDParam(0, p); + SetDParam(1, p); - TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK; + TextColour color = (p == sel) ? TC_WHITE : TC_BLACK; if (gray & 1) color = TC_GREY; DrawString(x + 19, y, STR_7021, color); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 76d872277b..00236df3cb 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2306,7 +2306,7 @@ static void UpdateTownGrowRate(Town *t) /* Increase player ratings if they're low */ const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && t->ratings[p->index] < RATING_GROWTH_MAXIMUM) { + if (t->ratings[p->index] < RATING_GROWTH_MAXIMUM) { t->ratings[p->index] = min((int)RATING_GROWTH_MAXIMUM, t->ratings[p->index] + RATING_GROWTH_UP_STEP); } } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 21569d6905..2d4399042e 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -182,7 +182,7 @@ public: const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && (HasBit(this->town->have_ratings, p->index) || this->town->exclusivity == p->index)) { + if ((HasBit(this->town->have_ratings, p->index) || this->town->exclusivity == p->index)) { DrawPlayerIcon(p->index, 2, y); SetDParam(0, p->index); diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 6f573fb176..07da7b56ff 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -23,6 +23,7 @@ #include "water_map.h" #include "water.h" #include "landscape_type.h" +#include "player_base.h" #include "table/strings.h" #include "table/sprites.h" diff --git a/src/tree_gui.cpp b/src/tree_gui.cpp index aec386fb02..7af060e704 100644 --- a/src/tree_gui.cpp +++ b/src/tree_gui.cpp @@ -8,6 +8,7 @@ #include "gfx_func.h" #include "tilehighlight_func.h" #include "player_func.h" +#include "player_base.h" #include "command_func.h" #include "sound_func.h" #include "settings_type.h"