date.cpp

Go to the documentation of this file.
00001 /* $Id: date.cpp 15077 2009-01-13 22:58:03Z smatz $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "variables.h"
00008 #include "settings_type.h"
00009 #include "network/network.h"
00010 #include "network/network_func.h"
00011 #include "currency.h"
00012 #include "window_func.h"
00013 #include "functions.h"
00014 #include "date_func.h"
00015 #include "vehicle_base.h"
00016 #include "debug.h"
00017 #include "rail_gui.h"
00018 #include "saveload/saveload.h"
00019 
00020 Year      _cur_year;   
00021 Month     _cur_month;  
00022 Date      _date;       
00023 DateFract _date_fract;
00024 
00025 
00026 void SetDate(Date date)
00027 {
00028   YearMonthDay ymd;
00029 
00030   _date = date;
00031   ConvertDateToYMD(date, &ymd);
00032   _cur_year = ymd.year;
00033   _cur_month = ymd.month;
00034 }
00035 
00036 #define M(a, b) ((a << 5) | b)
00037 static const uint16 _month_date_from_year_day[] = {
00038   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),
00039   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),
00040   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),
00041   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),
00042   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),
00043   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),
00044   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),
00045   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),
00046   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),
00047   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),
00048   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),
00049   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),
00050 };
00051 #undef M
00052 
00053 enum {
00054   ACCUM_JAN = 0,
00055   ACCUM_FEB = ACCUM_JAN + 31,
00056   ACCUM_MAR = ACCUM_FEB + 29,
00057   ACCUM_APR = ACCUM_MAR + 31,
00058   ACCUM_MAY = ACCUM_APR + 30,
00059   ACCUM_JUN = ACCUM_MAY + 31,
00060   ACCUM_JUL = ACCUM_JUN + 30,
00061   ACCUM_AUG = ACCUM_JUL + 31,
00062   ACCUM_SEP = ACCUM_AUG + 31,
00063   ACCUM_OCT = ACCUM_SEP + 30,
00064   ACCUM_NOV = ACCUM_OCT + 31,
00065   ACCUM_DEC = ACCUM_NOV + 30,
00066 };
00067 
00068 static const uint16 _accum_days_for_month[] = {
00069   ACCUM_JAN, ACCUM_FEB, ACCUM_MAR, ACCUM_APR,
00070   ACCUM_MAY, ACCUM_JUN, ACCUM_JUL, ACCUM_AUG,
00071   ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
00072 };
00073 
00079 void ConvertDateToYMD(Date date, YearMonthDay *ymd)
00080 {
00081   /*
00082    * Year determination in multiple steps to account for leap
00083    * years. First do the large steps, then the smaller ones.
00084    */
00085 
00086   /* There are 97 leap years in 400 years */
00087   Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
00088   int rem = date % (DAYS_IN_YEAR * 400 + 97);
00089   uint16 x;
00090 
00091   if (rem >= DAYS_IN_YEAR * 100 + 25) {
00092     /* There are 25 leap years in the first 100 years after
00093      * every 400th year, as every 400th year is a leap year */
00094     yr  += 100;
00095     rem -= DAYS_IN_YEAR * 100 + 25;
00096 
00097     /* There are 24 leap years in the next couple of 100 years */
00098     yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
00099     rem = (rem % (DAYS_IN_YEAR * 100 + 24));
00100   }
00101 
00102   if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
00103     /* The first 4 year of the century are not always a leap year */
00104     yr  += 4;
00105     rem -= DAYS_IN_YEAR * 4;
00106   }
00107 
00108   /* There is 1 leap year every 4 years */
00109   yr += 4 * (rem / (DAYS_IN_YEAR * 4 + 1));
00110   rem = rem % (DAYS_IN_YEAR * 4 + 1);
00111 
00112   /* The last (max 3) years to account for; the first one
00113    * can be, but is not necessarily a leap year */
00114   while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
00115     rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
00116     yr++;
00117   }
00118 
00119   /* Skip the 29th of February in non-leap years */
00120   if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++;
00121 
00122   ymd->year = yr;
00123 
00124   x = _month_date_from_year_day[rem];
00125   ymd->month = x >> 5;
00126   ymd->day = x & 0x1F;
00127 }
00128 
00135 Date ConvertYMDToDate(Year year, Month month, Day day)
00136 {
00137   /*
00138    * Each passed leap year adds one day to the 'day count'.
00139    *
00140    * A special case for the year 0 as no year has been passed,
00141    * but '(year - 1) / 4' does not yield '-1' to counteract the
00142    * '+1' at the end of the formula as divisions round to zero.
00143    */
00144   int nr_of_leap_years = (year == 0) ? 0 : ((year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400 + 1);
00145 
00146   /* Day-offset in a leap year */
00147   int days = _accum_days_for_month[month] + day - 1;
00148 
00149   /* Account for the missing of the 29th of February in non-leap years */
00150   if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
00151 
00152   return year * DAYS_IN_YEAR + nr_of_leap_years + days;
00153 }
00154 
00157 extern void WaypointsDailyLoop();
00158 extern void EnginesDailyLoop();
00159 extern void DisasterDailyLoop();
00160 extern void IndustryDailyLoop();
00161 extern void CompaniesMonthlyLoop();
00162 extern void EnginesMonthlyLoop();
00163 extern void TownsMonthlyLoop();
00164 extern void IndustryMonthlyLoop();
00165 extern void StationMonthlyLoop();
00166 
00167 extern void CompaniesYearlyLoop();
00168 extern void VehiclesYearlyLoop();
00169 extern void TownsYearlyLoop();
00170 
00171 extern void ShowEndGameChart();
00172 
00173 
00174 static const Month _autosave_months[] = {
00175    0, 
00176    1, 
00177    3, 
00178    6, 
00179   12, 
00180 };
00181 
00185 static void RunVehicleDayProc(uint daytick)
00186 {
00187   uint total = GetMaxVehicleIndex() + 1;
00188   uint i;
00189 
00190   for (i = daytick; i < total; i += DAY_TICKS) {
00191     Vehicle *v = GetVehicle(i);
00192 
00193     if (v->IsValid()) {
00194       /* Call the 32-day callback if needed */
00195       CheckVehicle32Day(v);
00196       v->OnNewDay();
00197     }
00198   }
00199 }
00200 
00201 void IncreaseDate()
00202 {
00203   YearMonthDay ymd;
00204 
00205   if (_game_mode == GM_MENU) {
00206     _tick_counter++;
00207     return;
00208   }
00209 
00210   RunVehicleDayProc(_date_fract);
00211 
00212   /* increase day, and check if a new day is there? */
00213   _tick_counter++;
00214 
00215   _date_fract++;
00216   if (_date_fract < DAY_TICKS) return;
00217   _date_fract = 0;
00218 
00219   /* yeah, increase day counter and call various daily loops */
00220   _date++;
00221 
00222 #ifdef ENABLE_NETWORK
00223   NetworkChatMessageDailyLoop();
00224 #endif /* ENABLE_NETWORK */
00225 
00226   DisasterDailyLoop();
00227   WaypointsDailyLoop();
00228   IndustryDailyLoop();
00229 
00230   if (_game_mode != GM_MENU) {
00231     InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
00232     EnginesDailyLoop();
00233   }
00234 
00235   /* check if we entered a new month? */
00236   ConvertDateToYMD(_date, &ymd);
00237   if (ymd.month == _cur_month) return;
00238   _cur_month = ymd.month;
00239 
00240   /* yes, call various monthly loops */
00241   if (_game_mode != GM_MENU) {
00242     if (_debug_desync_level > 2) {
00243       char name[MAX_PATH];
00244       snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
00245       SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
00246     }
00247 
00248     if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
00249       _do_autosave = true;
00250       RedrawAutosave();
00251     }
00252 
00253     InvalidateWindowClasses(WC_CHEATS);
00254     CompaniesMonthlyLoop();
00255     EnginesMonthlyLoop();
00256     TownsMonthlyLoop();
00257     IndustryMonthlyLoop();
00258     StationMonthlyLoop();
00259 #ifdef ENABLE_NETWORK
00260     if (_network_server) NetworkServerMonthlyLoop();
00261 #endif /* ENABLE_NETWORK */
00262   }
00263 
00264   /* check if we entered a new year? */
00265   if (ymd.year == _cur_year) return;
00266   _cur_year = ymd.year;
00267 
00268   /* yes, call various yearly loops */
00269   CompaniesYearlyLoop();
00270   VehiclesYearlyLoop();
00271   TownsYearlyLoop();
00272 #ifdef ENABLE_NETWORK
00273   if (_network_server) NetworkServerYearlyLoop();
00274 #endif /* ENABLE_NETWORK */
00275 
00276   if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
00277 
00278   /* check if we reached end of the game */
00279   if (_cur_year == ORIGINAL_END_YEAR) {
00280     ShowEndGameChart();
00281   /* check if we reached the maximum year, decrement dates by a year */
00282   } else if (_cur_year == MAX_YEAR + 1) {
00283     Vehicle *v;
00284     uint days_this_year;
00285 
00286     _cur_year--;
00287     days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
00288     _date -= days_this_year;
00289     FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
00290 
00291 #ifdef ENABLE_NETWORK
00292     /* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
00293      *  all of them if the date is set back, else those messages will hang for ever */
00294     NetworkInitChatMessage();
00295 #endif /* ENABLE_NETWORK */
00296   }
00297 
00298   if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
00299 }

Generated on Wed Jun 3 19:05:10 2009 for OpenTTD by  doxygen 1.5.6