* Start/initialise one engine. * @param e The engine to initialise. * @param aging_date The date used for age calculations. * @param seed Random seed. */
| 715 | * @param seed Random seed. |
| 716 | */ |
| 717 | void StartupOneEngine(Engine *e, const TimerGameCalendar::YearMonthDay &aging_ymd, uint32_t seed) |
| 718 | { |
| 719 | const EngineInfo *ei = &e->info; |
| 720 | |
| 721 | e->age = 0; |
| 722 | e->flags = {}; |
| 723 | e->company_avail = CompanyMask{}; |
| 724 | e->company_hidden = CompanyMask{}; |
| 725 | |
| 726 | /* Vehicles with the same base_intro date shall be introduced at the same time. |
| 727 | * Make sure they use the same randomisation of the date. */ |
| 728 | SavedRandomSeeds saved_seeds; |
| 729 | SaveRandomSeeds(&saved_seeds); |
| 730 | SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ |
| 731 | ei->base_intro.base() ^ |
| 732 | e->type ^ |
| 733 | e->GetGRFID()); |
| 734 | uint32_t r = Random(); |
| 735 | |
| 736 | /* Don't randomise the start-date in the first two years after gamestart to ensure availability |
| 737 | * of engines in early starting games. |
| 738 | * Note: TTDP uses fixed 1922 */ |
| 739 | e->intro_date = ei->base_intro <= TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (TimerGameCalendar::Date)GB(r, 0, 9) + ei->base_intro; |
| 740 | if (e->intro_date <= TimerGameCalendar::date) { |
| 741 | TimerGameCalendar::YearMonthDay intro_ymd = TimerGameCalendar::ConvertDateToYMD(e->intro_date); |
| 742 | int aging_months = aging_ymd.year.base() * 12 + aging_ymd.month; |
| 743 | int intro_months = intro_ymd.year.base() * 12 + intro_ymd.month; |
| 744 | if (intro_ymd.day > 1) intro_months++; // Engines are introduced at the first month start at/after intro date. |
| 745 | e->age = aging_months - intro_months; |
| 746 | e->company_avail.Set(); |
| 747 | e->flags.Set(EngineFlag::Available); |
| 748 | } |
| 749 | |
| 750 | /* Get parent variant index for syncing reliability via random seed. */ |
| 751 | const Engine *re = e; |
| 752 | while (re->info.variant_id != EngineID::Invalid() && re->info.extra_flags.Test(ExtraEngineFlag::SyncReliability)) { |
| 753 | re = Engine::Get(re->info.variant_id); |
| 754 | } |
| 755 | |
| 756 | SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ |
| 757 | (re->index.base() << 16) ^ (re->info.base_intro.base() << 12) ^ (re->info.decay_speed << 8) ^ |
| 758 | (re->info.lifelength.base() << 4) ^ re->info.retire_early ^ |
| 759 | e->type ^ |
| 760 | e->GetGRFID()); |
| 761 | |
| 762 | /* Base reliability defined as a percentage of UINT16_MAX. */ |
| 763 | const uint16_t RELIABILITY_START = UINT16_MAX * 48 / 100; |
| 764 | const uint16_t RELIABILITY_MAX = UINT16_MAX * 75 / 100; |
| 765 | const uint16_t RELIABILITY_FINAL = UINT16_MAX * 25 / 100; |
| 766 | |
| 767 | static_assert(RELIABILITY_START == 0x7AE0); |
| 768 | static_assert(RELIABILITY_MAX == 0xBFFF); |
| 769 | static_assert(RELIABILITY_FINAL == 0x3FFF); |
| 770 | |
| 771 | r = Random(); |
| 772 | /* 14 bits gives a value between 0 and 16383, which is up to an additional 25%p reliability on top of the base reliability. */ |
| 773 | e->reliability_start = GB(r, 16, 14) + RELIABILITY_START; |
| 774 | e->reliability_max = GB(r, 0, 14) + RELIABILITY_MAX; |
no test coverage detected