diff --git a/src/company_base.h b/src/company_base.h index 065931c6ce..dd2cfc23b8 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -17,6 +17,7 @@ #include "settings_type.h" #include "group.h" #include +#include /** Statistics about the economy. */ struct CompanyEconomyEntry { @@ -74,7 +75,7 @@ struct CompanyProperties { TileIndex location_of_HQ; ///< Northern tile of HQ; #INVALID_TILE when there is none. TileIndex last_build_coordinate; ///< Coordinate of the last build thing by this company. - Owner share_owners[4]; ///< Owners of the 4 shares of the company. #INVALID_OWNER if nobody has bought them yet. + std::array share_owners; ///< Owners of the shares of the company. #INVALID_OWNER if nobody has bought them yet. Year inaugurated_year; ///< Year of starting the company. diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index c1f68d2b63..99a2d5bd6c 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -67,7 +67,7 @@ Company::Company(uint16 name_1, bool is_ai) this->clear_limit = (uint32)_settings_game.construction.clear_frame_burst << 16; this->tree_limit = (uint32)_settings_game.construction.tree_frame_burst << 16; - for (uint j = 0; j < 4; j++) this->share_owners[j] = INVALID_OWNER; + std::fill(this->share_owners.begin(), this->share_owners.end(), INVALID_OWNER); InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY); } @@ -557,7 +557,7 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY) c->money = c->current_loan = (std::min(INITIAL_LOAN, _economy.max_loan) * _economy.inflation_prices >> 16) / 50000 * 50000; - c->share_owners[0] = c->share_owners[1] = c->share_owners[2] = c->share_owners[3] = INVALID_OWNER; + std::fill(c->share_owners.begin(), c->share_owners.end(), INVALID_OWNER); c->avail_railtypes = GetCompanyRailtypes(c->index); c->avail_roadtypes = GetCompanyRoadTypes(c->index); diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 66ef1a9898..6c4da6f746 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -2195,10 +2195,8 @@ static const NWidgetPart _nested_company_widgets[] = { int GetAmountOwnedBy(const Company *c, Owner owner) { - return (c->share_owners[0] == owner) + - (c->share_owners[1] == owner) + - (c->share_owners[2] == owner) + - (c->share_owners[3] == owner); + auto share_owned_by = [owner](auto share_owner) { return share_owner == owner; }; + return std::count_if(c->share_owners.begin(), c->share_owners.end(), share_owned_by); } /** Strings for the company vehicle counts */ @@ -2275,13 +2273,8 @@ struct CompanyWindow : Window } /* Owners of company */ - plane = SZSP_HORIZONTAL; - for (uint i = 0; i < lengthof(c->share_owners); i++) { - if (c->share_owners[i] != INVALID_COMPANY) { - plane = 0; - break; - } - } + auto invalid_owner = [](auto owner) { return owner == INVALID_COMPANY; }; + plane = std::all_of(c->share_owners.begin(), c->share_owners.end(), invalid_owner) ? SZSP_HORIZONTAL : 0; wi = this->GetWidget(WID_C_SELECT_DESC_OWNERS); if (plane != wi->shown_plane) { wi->SetDisplayedPlane(plane); diff --git a/src/company_type.h b/src/company_type.h index 8da3133082..3bbcf731e6 100644 --- a/src/company_type.h +++ b/src/company_type.h @@ -40,6 +40,7 @@ static const uint MAX_LENGTH_PRESIDENT_NAME_CHARS = 32; ///< The maximum length static const uint MAX_LENGTH_COMPANY_NAME_CHARS = 32; ///< The maximum length of a company name in characters including '\0' static const uint MAX_HISTORY_QUARTERS = 24; ///< The maximum number of quarters kept as performance's history +static const uint MAX_COMPANY_SHARE_OWNERS = 4; ///< The maximum number of shares of a company that can be owned by another company. /** Define basic enum properties */ template <> struct EnumPropsT : MakeEnumPropsT {}; diff --git a/src/economy.cpp b/src/economy.cpp index c6fd2ed398..4f10367821 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -306,43 +306,39 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) assert(old_owner != new_owner); - { - uint i; - - /* See if the old_owner had shares in other companies */ - for (const Company *c : Company::Iterate()) { - for (i = 0; i < 4; i++) { - if (c->share_owners[i] == old_owner) { - /* Sell its shares */ - CommandCost res = Command::Do(DC_EXEC | DC_BANKRUPT, c->index); - /* Because we are in a DoCommand, we can't just execute another one and - * expect the money to be removed. We need to do it ourself! */ - SubtractMoneyFromCompany(res); - } - } - } - - /* Sell all the shares that people have on this company */ - Backup cur_company2(_current_company, FILE_LINE); - Company *c = Company::Get(old_owner); - for (i = 0; i < 4; i++) { - if (c->share_owners[i] == INVALID_OWNER) continue; - - if (c->bankrupt_value == 0 && c->share_owners[i] == new_owner) { - /* You are the one buying the company; so don't sell the shares back to you. */ - c->share_owners[i] = INVALID_OWNER; - } else { - cur_company2.Change(c->share_owners[i]); - /* Sell the shares */ - CommandCost res = Command::Do(DC_EXEC | DC_BANKRUPT, old_owner); + /* See if the old_owner had shares in other companies */ + for (const Company *c : Company::Iterate()) { + for (auto share_owner : c->share_owners) { + if (share_owner == old_owner) { + /* Sell its shares */ + CommandCost res = Command::Do(DC_EXEC | DC_BANKRUPT, c->index); /* Because we are in a DoCommand, we can't just execute another one and * expect the money to be removed. We need to do it ourself! */ SubtractMoneyFromCompany(res); } } - cur_company2.Restore(); } + /* Sell all the shares that people have on this company */ + Backup cur_company2(_current_company, FILE_LINE); + Company *c = Company::Get(old_owner); + for (auto &share_owner : c->share_owners) { + if (share_owner == INVALID_OWNER) continue; + + if (c->bankrupt_value == 0 && share_owner == new_owner) { + /* You are the one buying the company; so don't sell the shares back to you. */ + share_owner = INVALID_OWNER; + } else { + cur_company2.Change(share_owner); + /* Sell the shares */ + CommandCost res = Command::Do(DC_EXEC | DC_BANKRUPT, old_owner); + /* Because we are in a DoCommand, we can't just execute another one and + * expect the money to be removed. We need to do it ourself! */ + SubtractMoneyFromCompany(res); + } + } + cur_company2.Restore(); + /* Temporarily increase the company's money, to be sure that * removing their property doesn't fail because of lack of money. * Not too drastically though, because it could overflow */ @@ -2029,9 +2025,9 @@ CommandCost CmdBuyShareInCompany(DoCommandFlag flags, TileIndex tile, CompanyID if (_cur_year - c->inaugurated_year < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED); /* Those lines are here for network-protection (clients can be slow) */ - if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost; + if (GetAmountOwnedBy(c, INVALID_OWNER) == 0) return cost; - if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1) { + if (GetAmountOwnedBy(c, INVALID_OWNER) == 1) { if (!c->is_ai) return cost; // We can not buy out a real company (temporarily). TODO: well, enable it obviously. if (GetAmountOwnedBy(c, _current_company) == 3 && !MayCompanyTakeOver(_current_company, target_company)) return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME); @@ -2040,17 +2036,14 @@ CommandCost CmdBuyShareInCompany(DoCommandFlag flags, TileIndex tile, CompanyID cost.AddCost(CalculateCompanyValue(c) >> 2); if (flags & DC_EXEC) { - Owner *b = c->share_owners; + auto unowned_share = std::find(c->share_owners.begin(), c->share_owners.end(), INVALID_OWNER); + assert(unowned_share != c->share_owners.end()); // share owners is guaranteed to contain at least one INVALID_OWNER, i.e. unowned share + *unowned_share = _current_company; - while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR - *b = _current_company; - - for (int i = 0; c->share_owners[i] == _current_company;) { - if (++i == 4) { - c->bankrupt_value = 0; - DoAcquireCompany(c); - break; - } + auto current_company_owns_share = [](auto share_owner) { return share_owner == _current_company; }; + if (std::all_of(c->share_owners.begin(), c->share_owners.end(), current_company_owns_share)) { + c->bankrupt_value = 0; + DoAcquireCompany(c); } InvalidateWindowData(WC_COMPANY, target_company); CompanyAdminUpdate(c); @@ -2083,9 +2076,9 @@ CommandCost CmdSellShareInCompany(DoCommandFlag flags, CompanyID target_company) cost = -(cost - (cost >> 7)); if (flags & DC_EXEC) { - Owner *b = c->share_owners; - while (*b != _current_company) b++; // share owners is guaranteed to contain company - *b = COMPANY_SPECTATOR; + auto our_owner = std::find(c->share_owners.begin(), c->share_owners.end(), _current_company); + assert(our_owner != c->share_owners.end()); // share owners is guaranteed to contain at least one INVALID_OWNER + *our_owner = INVALID_OWNER; InvalidateWindowData(WC_COMPANY, target_company); CompanyAdminUpdate(c); } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 4711cdf046..6729ece6c3 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -332,8 +332,8 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company p->Send_bool (c->is_ai); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy - for (size_t i = 0; i < lengthof(c->share_owners); i++) { - p->Send_uint8(c->share_owners[i]); + for (auto owner : c->share_owners) { + p->Send_uint8(owner); } this->SendPacket(p); @@ -359,8 +359,8 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Compa p->Send_bool (NetworkCompanyIsPassworded(c->index)); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy - for (size_t i = 0; i < lengthof(c->share_owners); i++) { - p->Send_uint8(c->share_owners[i]); + for (auto owner : c->share_owners) { + p->Send_uint8(owner); } this->SendPacket(p); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index ce26c1f5b2..4751ff6c43 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1755,10 +1755,9 @@ bool AfterLoadGame() * 2) shares that are owned by inactive companies or self * (caused by cheating clients in earlier revisions) */ for (Company *c : Company::Iterate()) { - for (uint i = 0; i < 4; i++) { - CompanyID company = c->share_owners[i]; - if (company == INVALID_COMPANY) continue; - if (!Company::IsValidID(company) || company == c->index) c->share_owners[i] = INVALID_COMPANY; + for (auto &share_owner : c->share_owners) { + if (share_owner == INVALID_COMPANY) continue; + if (!Company::IsValidID(share_owner) || share_owner == c->index) share_owner = INVALID_COMPANY; } } }