date.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "network/network.h"
00014 #include "network/network_func.h"
00015 #include "currency.h"
00016 #include "window_func.h"
00017 #include "settings_type.h"
00018 #include "date_func.h"
00019 #include "vehicle_base.h"
00020 #include "rail_gui.h"
00021 #include "saveload/saveload.h"
00022 #include "cargodest_func.h"
00023 
00024 Year      _cur_year;   
00025 Month     _cur_month;  
00026 Date      _date;       
00027 DateFract _date_fract; 
00028 uint16 _tick_counter;  
00029 
00035 void SetDate(Date date, DateFract fract)
00036 {
00037   assert(fract < DAY_TICKS);
00038 
00039   YearMonthDay ymd;
00040 
00041   _date = date;
00042   _date_fract = fract;
00043   ConvertDateToYMD(date, &ymd);
00044   _cur_year = ymd.year;
00045   _cur_month = ymd.month;
00046 }
00047 
00048 #define M(a, b) ((a << 5) | b)
00049 static const uint16 _month_date_from_year_day[] = {
00050   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),
00051   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),
00052   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),
00053   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),
00054   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),
00055   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),
00056   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),
00057   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),
00058   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),
00059   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),
00060   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),
00061   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),
00062 };
00063 #undef M
00064 
00065 enum DaysTillMonth {
00066   ACCUM_JAN = 0,
00067   ACCUM_FEB = ACCUM_JAN + 31,
00068   ACCUM_MAR = ACCUM_FEB + 29,
00069   ACCUM_APR = ACCUM_MAR + 31,
00070   ACCUM_MAY = ACCUM_APR + 30,
00071   ACCUM_JUN = ACCUM_MAY + 31,
00072   ACCUM_JUL = ACCUM_JUN + 30,
00073   ACCUM_AUG = ACCUM_JUL + 31,
00074   ACCUM_SEP = ACCUM_AUG + 31,
00075   ACCUM_OCT = ACCUM_SEP + 30,
00076   ACCUM_NOV = ACCUM_OCT + 31,
00077   ACCUM_DEC = ACCUM_NOV + 30,
00078 };
00079 
00081 static const uint16 _accum_days_for_month[] = {
00082   ACCUM_JAN, ACCUM_FEB, ACCUM_MAR, ACCUM_APR,
00083   ACCUM_MAY, ACCUM_JUN, ACCUM_JUL, ACCUM_AUG,
00084   ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
00085 };
00086 
00092 void ConvertDateToYMD(Date date, YearMonthDay *ymd)
00093 {
00094   /* Year determination in multiple steps to account for leap
00095    * years. First do the large steps, then the smaller ones.
00096    */
00097 
00098   /* There are 97 leap years in 400 years */
00099   Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
00100   int rem = date % (DAYS_IN_YEAR * 400 + 97);
00101   uint16 x;
00102 
00103   if (rem >= DAYS_IN_YEAR * 100 + 25) {
00104     /* There are 25 leap years in the first 100 years after
00105      * every 400th year, as every 400th year is a leap year */
00106     yr  += 100;
00107     rem -= DAYS_IN_YEAR * 100 + 25;
00108 
00109     /* There are 24 leap years in the next couple of 100 years */
00110     yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
00111     rem = (rem % (DAYS_IN_YEAR * 100 + 24));
00112   }
00113 
00114   if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
00115     /* The first 4 year of the century are not always a leap year */
00116     yr  += 4;
00117     rem -= DAYS_IN_YEAR * 4;
00118   }
00119 
00120   /* There is 1 leap year every 4 years */
00121   yr += 4 * (rem / (DAYS_IN_YEAR * 4 + 1));
00122   rem = rem % (DAYS_IN_YEAR * 4 + 1);
00123 
00124   /* The last (max 3) years to account for; the first one
00125    * can be, but is not necessarily a leap year */
00126   while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
00127     rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
00128     yr++;
00129   }
00130 
00131   /* Skip the 29th of February in non-leap years */
00132   if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++;
00133 
00134   ymd->year = yr;
00135 
00136   x = _month_date_from_year_day[rem];
00137   ymd->month = x >> 5;
00138   ymd->day = x & 0x1F;
00139 }
00140 
00147 Date ConvertYMDToDate(Year year, Month month, Day day)
00148 {
00149   /* Day-offset in a leap year */
00150   int days = _accum_days_for_month[month] + day - 1;
00151 
00152   /* Account for the missing of the 29th of February in non-leap years */
00153   if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
00154 
00155   return DAYS_TILL(year) + days;
00156 }
00157 
00160 extern void EnginesDailyLoop();
00161 extern void DisasterDailyLoop();
00162 extern void IndustryDailyLoop();
00163 
00164 extern void CompaniesMonthlyLoop();
00165 extern void EnginesMonthlyLoop();
00166 extern void TownsMonthlyLoop();
00167 extern void IndustryMonthlyLoop();
00168 extern void StationMonthlyLoop();
00169 extern void SubsidyMonthlyLoop();
00170 
00171 extern void CompaniesYearlyLoop();
00172 extern void VehiclesYearlyLoop();
00173 extern void TownsYearlyLoop();
00174 
00175 extern void ShowEndGameChart();
00176 
00177 
00179 static const Month _autosave_months[] = {
00180    0, 
00181    1, 
00182    3, 
00183    6, 
00184   12, 
00185 };
00186 
00190 static void OnNewYear()
00191 {
00192   CompaniesYearlyLoop();
00193   VehiclesYearlyLoop();
00194   TownsYearlyLoop();
00195   InvalidateWindowClassesData(WC_BUILD_STATION);
00196 #ifdef ENABLE_NETWORK
00197   if (_network_server) NetworkServerYearlyLoop();
00198 #endif /* ENABLE_NETWORK */
00199 
00200   if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
00201 
00202   /* check if we reached end of the game */
00203   if (_cur_year == ORIGINAL_END_YEAR) {
00204     ShowEndGameChart();
00205   /* check if we reached the maximum year, decrement dates by a year */
00206   } else if (_cur_year == MAX_YEAR + 1) {
00207     Vehicle *v;
00208     uint days_this_year;
00209 
00210     _cur_year--;
00211     days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
00212     _date -= days_this_year;
00213     FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
00214 
00215 #ifdef ENABLE_NETWORK
00216     /* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
00217      *  all of them if the date is set back, else those messages will hang for ever */
00218     NetworkInitChatMessage();
00219 #endif /* ENABLE_NETWORK */
00220   }
00221 
00222   if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
00223 }
00224 
00228 static void OnNewMonth()
00229 {
00230   if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
00231     _do_autosave = true;
00232     SetWindowDirty(WC_STATUS_BAR, 0);
00233   }
00234 
00235   SetWindowClassesDirty(WC_CHEATS);
00236   CompaniesMonthlyLoop();
00237   SubsidyMonthlyLoop();
00238   EnginesMonthlyLoop();
00239   TownsMonthlyLoop();
00240   IndustryMonthlyLoop();
00241   StationMonthlyLoop();
00242   UpdateCargoLinks();
00243 #ifdef ENABLE_NETWORK
00244   if (_network_server) NetworkServerMonthlyLoop();
00245 #endif /* ENABLE_NETWORK */
00246 }
00247 
00251 static void OnNewDay()
00252 {
00253 #ifdef ENABLE_NETWORK
00254   if (_network_server) NetworkServerDailyLoop();
00255 #endif /* ENABLE_NETWORK */
00256 
00257   DisasterDailyLoop();
00258   IndustryDailyLoop();
00259 
00260   SetWindowWidgetDirty(WC_STATUS_BAR, 0, 0);
00261   EnginesDailyLoop();
00262 
00263   /* Refresh after possible snowline change */
00264   SetWindowClassesDirty(WC_TOWN_VIEW);
00265 }
00266 
00271 void IncreaseDate()
00272 {
00273   /* increase day, and check if a new day is there? */
00274   _tick_counter++;
00275 
00276   if (_game_mode == GM_MENU) return;
00277 
00278   _date_fract++;
00279   if (_date_fract < DAY_TICKS) return;
00280   _date_fract = 0;
00281 
00282   /* increase day counter and call various daily loops */
00283   _date++;
00284   OnNewDay();
00285 
00286   YearMonthDay ymd;
00287 
00288   /* check if we entered a new month? */
00289   ConvertDateToYMD(_date, &ymd);
00290   if (ymd.month == _cur_month) return;
00291 
00292   /* yes, call various monthly loops */
00293   _cur_month = ymd.month;
00294   OnNewMonth();
00295 
00296   /* check if we entered a new year? */
00297   if (ymd.year == _cur_year) return;
00298 
00299   /* yes, call various yearly loops */
00300   _cur_year = ymd.year;
00301   OnNewYear();
00302 }

Generated on Mon May 9 05:18:52 2011 for OpenTTD by  doxygen 1.6.1