date.cpp

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

Generated on Sun Nov 14 14:41:50 2010 for OpenTTD by  doxygen 1.6.1