date.cpp

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

Generated on Wed Oct 1 17:03:20 2008 for openttd by  doxygen 1.5.6