Loading

code

  1. /* $Id$ */
  2.  
  3. /*
  4.  * This file is part of OpenTTD.
  5.  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
  6.  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  7.  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
  8.  */
  9.  
  10. /** @file date.cpp Handling of dates in our native format and transforming them to something human readable. */
  11.  
  12. #include "stdafx.h"
  13. #include "network/network.h"
  14. #include "network/network_func.h"
  15. #include "currency.h"
  16. #include "window_func.h"
  17. #include "settings_type.h"
  18. #include "date_func.h"
  19. #include "vehicle_base.h"
  20. #include "rail_gui.h"
  21. #include "linkgraph/linkgraph.h"
  22. #include "saveload/saveload.h"
  23.  
  24. #include "safeguards.h"
  25. unsigned char _leap; ///< 0 or 1 depending if it is leap year
  26. unsigned char _leap4; ///< check if year in multiple of 4
  27. unsigned char _leap100; ///< check if year in multiple of 100
  28. short int _leap400; ///< check if year in multiple of 400
  29. Year      _cur_year;   ///< Current year, starting at 0
  30. Month     _cur_month;  ///< Current month (0..11)
  31. unsigned char _slowD ;       ///< factor of slowing game down , 1 is normal speed
  32. Date      _date;       ///< Current date in days (day counter)
  33. unsigned char _yearn ;       ///< regular game year
  34. unsigned char _monthn;       ///< regular game month
  35. unsigned char _dayn;       ///< regular game day
  36. unsigned char _dayh;       ///< counter for game month  
  37. unsigned char _daym ;       ///< days in month
  38. DateFract _date_fract; ///< Fractional part of the day.
  39. uint16 _tick_counter;  ///< Ever incrementing (and sometimes wrapping) tick counter for setting off various events
  40.  
  41. /**
  42.  * Set the date.
  43.  * @param date  New date
  44.  * @param fract The number of ticks that have passed on this date.
  45.  */
  46. void SetDate(Date date, DateFract fract)
  47. {
  48.     assert(fract < DAY_TICKS);
  49.  
  50.     YearMonthDay ymd;
  51.  
  52.     _date = date;
  53.     _date_fract = fract;
  54.     ConvertDateToYMD(date, &ymd);
  55.     _cur_year = ymd.year;
  56.     _cur_month = ymd.month;
  57.     _leap4 = _cur_year % 4;
  58.     _leap100 = _cur_year % 100;
  59.     _leap400 = _cur_year % 400;
  60.     _slowD = 2;       ///< this need to be user defined
  61.     _yearn= 0;
  62.     _monthn = 0;
  63.     _dayn =0;
  64.     _dayh = ymd.day; /// does this gives the day of  month we are in???
  65.    
  66. }
  67. void  Set_leap()
  68. {
  69.  
  70. if (_leap4==0){
  71. if (_leap100==0){
  72. if (_leap400==0){
  73. _leap=1;
  74. }
  75. else
  76. {
  77. _leap=0;
  78. }
  79. }
  80. else
  81. {
  82. }
  83. }
  84. else
  85. {
  86. _leap=0;
  87. }
  88.  
  89.  
  90.  
  91. }
  92. void Set_daym()
  93.  {
  94. switch (_cur_month) {
  95. case 0:
  96. _daym= 31;
  97. break;
  98. case 1:
  99. _daym= 28 + _leap;
  100. break;
  101. case 2:
  102. _daym= 31;
  103. break;
  104. case 3:
  105. _daym=30;
  106. break;
  107. case 4:
  108. _daym=31;
  109. break;
  110. case 5:
  111. _daym=30;
  112. break;
  113. case 6:
  114. _daym=31;
  115. break;
  116. case 7:
  117. _daym=31;
  118. break;
  119. case 8:
  120. _daym=30;
  121. break;
  122. case 9:
  123. _daym= 31;
  124. break;
  125. case 10:
  126. _daym=30;
  127. break;
  128. case 11:
  129. _daym=31;
  130. break;
  131. }
  132.  
  133. }
  134.  
  135.  
  136. #define M(a, b) ((a << 5) | b)
  137. static const uint16 _month_date_from_year_day[] = {
  138.     M( 0, 1), M( 0, 2), M( 0, 3), M( 0, 4), M( 0, 5), M( 0, 6), M( 0, 7), M( 0, 8), M( 0, 9), M( 0, 10), M( 0, 11), M( 0, 12), M( 0, 13), M( 0, 14), M( 0, 15), M( 0, 16), M( 0, 17), M( 0, 18), M( 0, 19), M( 0, 20), M( 0, 21), M( 0, 22), M( 0, 23), M( 0, 24), M( 0, 25), M( 0, 26), M( 0, 27), M( 0, 28), M( 0, 29), M( 0, 30), M( 0, 31),
  139.     M( 1, 1), M( 1, 2), M( 1, 3), M( 1, 4), M( 1, 5), M( 1, 6), M( 1, 7), M( 1, 8), M( 1, 9), M( 1, 10), M( 1, 11), M( 1, 12), M( 1, 13), M( 1, 14), M( 1, 15), M( 1, 16), M( 1, 17), M( 1, 18), M( 1, 19), M( 1, 20), M( 1, 21), M( 1, 22), M( 1, 23), M( 1, 24), M( 1, 25), M( 1, 26), M( 1, 27), M( 1, 28), M( 1, 29),
  140.     M( 2, 1), M( 2, 2), M( 2, 3), M( 2, 4), M( 2, 5), M( 2, 6), M( 2, 7), M( 2, 8), M( 2, 9), M( 2, 10), M( 2, 11), M( 2, 12), M( 2, 13), M( 2, 14), M( 2, 15), M( 2, 16), M( 2, 17), M( 2, 18), M( 2, 19), M( 2, 20), M( 2, 21), M( 2, 22), M( 2, 23), M( 2, 24), M( 2, 25), M( 2, 26), M( 2, 27), M( 2, 28), M( 2, 29), M( 2, 30), M( 2, 31),
  141.     M( 3, 1), M( 3, 2), M( 3, 3), M( 3, 4), M( 3, 5), M( 3, 6), M( 3, 7), M( 3, 8), M( 3, 9), M( 3, 10), M( 3, 11), M( 3, 12), M( 3, 13), M( 3, 14), M( 3, 15), M( 3, 16), M( 3, 17), M( 3, 18), M( 3, 19), M( 3, 20), M( 3, 21), M( 3, 22), M( 3, 23), M( 3, 24), M( 3, 25), M( 3, 26), M( 3, 27), M( 3, 28), M( 3, 29), M( 3, 30),
  142.     M( 4, 1), M( 4, 2), M( 4, 3), M( 4, 4), M( 4, 5), M( 4, 6), M( 4, 7), M( 4, 8), M( 4, 9), M( 4, 10), M( 4, 11), M( 4, 12), M( 4, 13), M( 4, 14), M( 4, 15), M( 4, 16), M( 4, 17), M( 4, 18), M( 4, 19), M( 4, 20), M( 4, 21), M( 4, 22), M( 4, 23), M( 4, 24), M( 4, 25), M( 4, 26), M( 4, 27), M( 4, 28), M( 4, 29), M( 4, 30), M( 4, 31),
  143.     M( 5, 1), M( 5, 2), M( 5, 3), M( 5, 4), M( 5, 5), M( 5, 6), M( 5, 7), M( 5, 8), M( 5, 9), M( 5, 10), M( 5, 11), M( 5, 12), M( 5, 13), M( 5, 14), M( 5, 15), M( 5, 16), M( 5, 17), M( 5, 18), M( 5, 19), M( 5, 20), M( 5, 21), M( 5, 22), M( 5, 23), M( 5, 24), M( 5, 25), M( 5, 26), M( 5, 27), M( 5, 28), M( 5, 29), M( 5, 30),
  144.     M( 6, 1), M( 6, 2), M( 6, 3), M( 6, 4), M( 6, 5), M( 6, 6), M( 6, 7), M( 6, 8), M( 6, 9), M( 6, 10), M( 6, 11), M( 6, 12), M( 6, 13), M( 6, 14), M( 6, 15), M( 6, 16), M( 6, 17), M( 6, 18), M( 6, 19), M( 6, 20), M( 6, 21), M( 6, 22), M( 6, 23), M( 6, 24), M( 6, 25), M( 6, 26), M( 6, 27), M( 6, 28), M( 6, 29), M( 6, 30), M( 6, 31),
  145.     M( 7, 1), M( 7, 2), M( 7, 3), M( 7, 4), M( 7, 5), M( 7, 6), M( 7, 7), M( 7, 8), M( 7, 9), M( 7, 10), M( 7, 11), M( 7, 12), M( 7, 13), M( 7, 14), M( 7, 15), M( 7, 16), M( 7, 17), M( 7, 18), M( 7, 19), M( 7, 20), M( 7, 21), M( 7, 22), M( 7, 23), M( 7, 24), M( 7, 25), M( 7, 26), M( 7, 27), M( 7, 28), M( 7, 29), M( 7, 30), M( 7, 31),
  146.     M( 8, 1), M( 8, 2), M( 8, 3), M( 8, 4), M( 8, 5), M( 8, 6), M( 8, 7), M( 8, 8), M( 8, 9), M( 8, 10), M( 8, 11), M( 8, 12), M( 8, 13), M( 8, 14), M( 8, 15), M( 8, 16), M( 8, 17), M( 8, 18), M( 8, 19), M( 8, 20), M( 8, 21), M( 8, 22), M( 8, 23), M( 8, 24), M( 8, 25), M( 8, 26), M( 8, 27), M( 8, 28), M( 8, 29), M( 8, 30),
  147.     M( 9, 1), M( 9, 2), M( 9, 3), M( 9, 4), M( 9, 5), M( 9, 6), M( 9, 7), M( 9, 8), M( 9, 9), M( 9, 10), M( 9, 11), M( 9, 12), M( 9, 13), M( 9, 14), M( 9, 15), M( 9, 16), M( 9, 17), M( 9, 18), M( 9, 19), M( 9, 20), M( 9, 21), M( 9, 22), M( 9, 23), M( 9, 24), M( 9, 25), M( 9, 26), M( 9, 27), M( 9, 28), M( 9, 29), M( 9, 30), M( 9, 31),
  148.     M(10, 1), M(10, 2), M(10, 3), M(10, 4), M(10, 5), M(10, 6), M(10, 7), M(10, 8), M(10, 9), M(10, 10), M(10, 11), M(10, 12), M(10, 13), M(10, 14), M(10, 15), M(10, 16), M(10, 17), M(10, 18), M(10, 19), M(10, 20), M(10, 21), M(10, 22), M(10, 23), M(10, 24), M(10, 25), M(10, 26), M(10, 27), M(10, 28), M(10, 29), M(10, 30),
  149.     M(11, 1), M(11, 2), M(11, 3), M(11, 4), M(11, 5), M(11, 6), M(11, 7), M(11, 8), M(11, 9), M(11, 10), M(11, 11), M(11, 12), M(11, 13), M(11, 14), M(11, 15), M(11, 16), M(11, 17), M(11, 18), M(11, 19), M(11, 20), M(11, 21), M(11, 22), M(11, 23), M(11, 24), M(11, 25), M(11, 26), M(11, 27), M(11, 28), M(11, 29), M(11, 30), M(11, 31),
  150. };
  151. #undef M
  152.  
  153. enum DaysTillMonth {
  154.     ACCUM_JAN = 0,
  155.     ACCUM_FEB = ACCUM_JAN + 31,
  156.     ACCUM_MAR = ACCUM_FEB + 29,
  157.     ACCUM_APR = ACCUM_MAR + 31,
  158.     ACCUM_MAY = ACCUM_APR + 30,
  159.     ACCUM_JUN = ACCUM_MAY + 31,
  160.     ACCUM_JUL = ACCUM_JUN + 30,
  161.     ACCUM_AUG = ACCUM_JUL + 31,
  162.     ACCUM_SEP = ACCUM_AUG + 31,
  163.     ACCUM_OCT = ACCUM_SEP + 30,
  164.     ACCUM_NOV = ACCUM_OCT + 31,
  165.     ACCUM_DEC = ACCUM_NOV + 30,
  166. };
  167.  
  168. /** Number of days to pass from the first day in the year before reaching the first of a month. */
  169. static const uint16 _accum_days_for_month[] = {
  170.     ACCUM_JAN, ACCUM_FEB, ACCUM_MAR, ACCUM_APR,
  171.     ACCUM_MAY, ACCUM_JUN, ACCUM_JUL, ACCUM_AUG,
  172.     ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
  173. };
  174.  
  175. /**
  176.  * Converts a Date to a Year, Month & Day.
  177.  * @param date the date to convert from
  178.  * @param ymd  the year, month and day to write to
  179.  */
  180. void ConvertDateToYMD(Date date, YearMonthDay *ymd)
  181. {
  182.     /* Year determination in multiple steps to account for leap
  183.      * years. First do the large steps, then the smaller ones.
  184.      */
  185.  
  186.     /* There are 97 leap years in 400 years */
  187.     Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
  188.     int rem = date % (DAYS_IN_YEAR * 400 + 97);
  189.     uint16 x;
  190.  
  191.     if (rem >= DAYS_IN_YEAR * 100 + 25) {
  192.         /* There are 25 leap years in the first 100 years after
  193.          * every 400th year, as every 400th year is a leap year */
  194.         yr  += 100;
  195.         rem -= DAYS_IN_YEAR * 100 + 25;
  196.  
  197.         /* There are 24 leap years in the next couple of 100 years */
  198.         yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
  199.         rem = (rem % (DAYS_IN_YEAR * 100 + 24));
  200.     }
  201.  
  202.     if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
  203.         /* The first 4 year of the century are not always a leap year */
  204.         yr  += 4;
  205.         rem -= DAYS_IN_YEAR * 4;
  206.     }
  207.  
  208.     /* There is 1 leap year every 4 years */
  209.     yr += 4 * (rem / (DAYS_IN_YEAR * 4 + 1));
  210.     rem = rem % (DAYS_IN_YEAR * 4 + 1);
  211.  
  212.     /* The last (max 3) years to account for; the first one
  213.      * can be, but is not necessarily a leap year */
  214.     while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
  215.         rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
  216.         yr++;
  217.     }
  218.  
  219.     /* Skip the 29th of February in non-leap years */
  220.     if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++;
  221.  
  222.     ymd->year = yr;
  223.  
  224.     x = _month_date_from_year_day[rem];
  225.     ymd->month = x >> 5;
  226.     ymd->day = x & 0x1F;
  227. }
  228.  
  229. /**
  230.  * Converts a tuple of Year, Month and Day to a Date.
  231.  * @param year  is a number between 0..MAX_YEAR
  232.  * @param month is a number between 0..11
  233.  * @param day   is a number between 1..31
  234.  */
  235. Date ConvertYMDToDate(Year year, Month month, Day day)
  236. {
  237.     /* Day-offset in a leap year */
  238.     int days = _accum_days_for_month[month] + day - 1;
  239.  
  240.     /* Account for the missing of the 29th of February in non-leap years */
  241.     if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
  242.  
  243.     return DAYS_TILL(year) + days;
  244. }
  245.  
  246. /** Functions used by the IncreaseDate function */
  247.  
  248. extern void EnginesDailyLoop();
  249. extern void DisasterDailyLoop();
  250. extern void IndustryDailyLoop();
  251.  
  252. extern void CompaniesMonthlyLoop();
  253. extern void EnginesMonthlyLoop();
  254. extern void TownsMonthlyLoop();
  255. extern void IndustryMonthlyLoop();
  256. extern void StationMonthlyLoop();
  257. extern void SubsidyMonthlyLoop();
  258.  
  259. extern void CompaniesYearlyLoop();
  260. extern void VehiclesYearlyLoop();
  261. extern void TownsYearlyLoop();
  262.  
  263. extern void ShowEndGameChart();
  264.  
  265.  
  266. /** Available settings for autosave intervals. */
  267. static const Month _autosave_months[] = {
  268.      0, ///< never
  269.      1, ///< every month
  270.      3, ///< every 3 months
  271.      6, ///< every 6 months
  272.     12, ///< every 12 months
  273. };
  274.  
  275. /**
  276.  * Runs various procedures that have to be done yearly
  277.  */
  278. static void OnNewYear()
  279. {
  280.     VehiclesYearlyLoop();
  281.     TownsYearlyLoop();
  282.     InvalidateWindowClassesData(WC_BUILD_STATION);
  283. #ifdef ENABLE_NETWORK
  284.     if (_network_server) NetworkServerYearlyLoop();
  285. #endif /* ENABLE_NETWORK */
  286.  
  287.     if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
  288.  
  289.     /* check if we reached end of the game */
  290.     if (_cur_year == ORIGINAL_END_YEAR) {
  291.         ShowEndGameChart();
  292.     /* check if we reached the maximum year, decrement dates by a year */
  293.     } else if (_cur_year == MAX_YEAR + 1) {
  294.         Vehicle *v;
  295.         int days_this_year;
  296.  
  297.         _cur_year--;
  298.         days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
  299.         _date -= days_this_year;
  300.         FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
  301.  
  302.  
  303. #ifdef ENABLE_NETWORK
  304.         /* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
  305.          *  all of them if the date is set back, else those messages will hang for ever */
  306.         NetworkInitChatMessage();
  307. #endif /* ENABLE_NETWORK */
  308.     }
  309.  
  310.     if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
  311. }
  312.  
  313. /**
  314.  * Runs various procedures that have to be done monthly
  315.  */
  316. static void OnNewMonth()
  317. {
  318.     if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
  319.         _do_autosave = true;
  320.         SetWindowDirty(WC_STATUS_BAR, 0);
  321.     }
  322.  
  323.     SetWindowClassesDirty(WC_CHEATS);
  324.     CompaniesMonthlyLoop();
  325.     EnginesMonthlyLoop();
  326.     TownsMonthlyLoop();
  327.     IndustryMonthlyLoop();
  328.     SubsidyMonthlyLoop();
  329.     StationMonthlyLoop();
  330. #ifdef ENABLE_NETWORK
  331.     if (_network_server) NetworkServerMonthlyLoop();
  332. #endif /* ENABLE_NETWORK */
  333. }
  334.  
  335. /**
  336.  * Runs various procedures that have to be done daily
  337.  */
  338. static void OnNewDay()
  339. {
  340. #ifdef ENABLE_NETWORK
  341.     if (_network_server) NetworkServerDailyLoop();
  342. #endif /* ENABLE_NETWORK */
  343.  
  344.     DisasterDailyLoop();
  345.     IndustryDailyLoop();
  346.  
  347.     SetWindowWidgetDirty(WC_STATUS_BAR, 0, 0);
  348.     EnginesDailyLoop();
  349.  
  350.     /* Refresh after possible snowline change */
  351.     SetWindowClassesDirty(WC_TOWN_VIEW);
  352. }
  353.  
  354. /**
  355.  * Increases the tick counter, increases date  and possibly calls
  356.  * procedures that have to be called daily, monthly or yearly.
  357.  */
  358.  
  359. static void OnNewYearS()
  360. {
  361. CompaniesYearlyLoop();
  362. if (_cur_year == ORIGINAL_END_YEAR) {
  363.         ShowEndGameChart();
  364.     /* check if we reached the maximum year, decrement dates by a year */
  365.     } else if (_cur_year == MAX_YEAR + 1) {
  366.         Vehicle *v;
  367.         int days_this_year;
  368.  
  369.         _cur_year--;
  370.         days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
  371.         _date -= days_this_year;
  372.         FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
  373.  
  374.  
  375. LinkGraph *lg;
  376.         FOR_ALL_LINK_GRAPHS(lg) lg->ShiftDates(-days_this_year);
  377. _leap4++;
  378. if (_leap4 >3) {
  379. _leap4=0;
  380. }
  381. _leap100++;
  382. if (_leap100 >99) {
  383. _leap100=0;
  384. }
  385. _leap400++;
  386. if (_leap400 >399) {
  387. _leap400=0;
  388. }
  389.  
  390.  
  391. Set_leap();
  392. Set_daym();
  393. }
  394.  
  395. static void OnNewMonthS()
  396. {
  397. }
  398.  
  399.  
  400. static void OnNewDayS()
  401. {
  402. }
  403.  
  404. void IncreaseDate()
  405. {
  406.     /* increase day, and check if a new day is there? */
  407.     _tick_counter++;
  408.  
  409.     if (_game_mode == GM_MENU) return;
  410.  
  411.     _date_fract++;
  412.     if (_date_fract < DAY_TICKS) return;
  413.     _date_fract = 0;
  414.  
  415.     /* increase day counter */
  416.     _dayn++;
  417.     _dayh++;
  418.     OnNewDay();
  419.  
  420. if (_dayn == _slowD)
  421. {
  422. _dayn  = 0;
  423. _date++;
  424. OnNewDayS();
  425. }
  426. if (_dayh > _daym)
  427. {
  428. _dayh = 1;
  429. _monthn ++;
  430. OnNewMonth();
  431. }
  432. if (_monthn == _slowD)
  433. {
  434. _monthn=0;
  435. _cur_month++;
  436. Set_daym();
  437. OnNewMonthS();
  438. }
  439. If (_cur_month==12)
  440. {
  441. _cur_month =0;
  442. OnNewYear();
  443. _yearn++;
  444. }
  445. if (_yearn == _slowD)
  446. {
  447. _yearn=0;
  448. _cur_year++;
  449. OnNewYearS();
  450. }
  451. }

Comments