changeset 4326:81a3d560c885 draft

(svn r5999) -Feature: change the original date format to a 32 bits format based at the year 0. The game date subsystem now allows someone to start in the year 0 and continue up to the year 5 000 000. However, you currently cannot build anything before 1920 as there is no newgrf support for dates before 1920 or after 2090 yet.
author rubidium <rubidium@openttd.org>
date Sun, 20 Aug 2006 18:40:57 +0000
parents 06559d8dfdcc
children 4e20530809a5
files date.c date.h engine.c engine.h genworld_gui.c industry.h industry_cmd.c misc.c misc_gui.c network.h network_client.c network_data.h network_server.c network_udp.c oldloader.c openttd.c openttd.h player.h players.c saveload.c settings.c station_cmd.c vehicle.c vehicle.h waypoint.c
diffstat 25 files changed, 161 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/date.c
+++ b/date.c
@@ -70,25 +70,47 @@
 	ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
 };
 
+static inline bool IsLeapYear(Year yr)
+{
+	return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0);
+}
 
+/**
+ * Converts a Date to a Year, Month & Day.
+ * @param date the date to convert from
+ * @param ymd  the year, month and day to write to
+ */
 void ConvertDateToYMD(Date date, YearMonthDay *ymd)
 {
-	uint yr  = date / (365 + 365 + 365 + 366);
-	uint rem = date % (365 + 365 + 365 + 366);
-	uint x;
+	/*
+	 * Year determination in multiple steps to account for leap
+	 * years. First do the large steps, then the smaller ones.
+	 */
 
-	yr *= 4;
+	/* There are 97 leap years in 400 years */
+	Year yr = 400 * (date / (365 * 400 + 97));
+	int rem = date % (365 * 400 + 97);
+	uint16 x;
 
-	if (rem >= 366) {
-		rem--;
-		do {
-			rem -= 365;
-			yr++;
-		} while (rem >= 365);
-		if (rem >= 31 + 28) rem++;
+	/* There are 24 leap years in 100 years */
+	yr += 100 * (rem / (365 * 100 + 24));
+	rem = rem % (365 * 100 + 24);
+
+	/* There is 1 leap year every 4 years */
+	yr += 4 * (rem / (365 * 4 + 1));
+	rem = rem % (365 * 4 + 1);
+
+	/* The last (max 3) years to account for; the first one
+	 * can be, but is not necessarily a leap year */
+	while (rem >= (IsLeapYear(yr) ? 366 : 365)) {
+		rem -= IsLeapYear(yr) ? 366 : 365;
+		yr++;
 	}
 
-	ymd->year = BASE_YEAR + yr;
+	/* Skip the 29th of February in non-leap years */
+	if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++;
+
+	ymd->year = yr;
 
 	x = _month_date_from_year_day[rem];
 	ymd->month = x >> 5;
@@ -97,23 +119,28 @@
 
 /**
  * Converts a tupe of Year, Month and Day to a Date.
- * @param year  is a number between 0..?
+ * @param year  is a number between 0..MAX_YEAR
  * @param month is a number between 0..11
  * @param day   is a number between 1..31
  */
 Date ConvertYMDToDate(Year year, Month month, Day day)
 {
-	uint rem;
-	uint yr = year - BASE_YEAR;
-
-	/* day in the year */
-	rem = _accum_days_for_month[month] + day - 1;
+	/*
+	 * Each passed leap year adds one day to the 'day count'.
+	 *
+	 * A special case for the year 0 as no year has been passed,
+	 * but '(year - 1) / 4' does not yield '-1' to counteract the
+	 * '+1' at the end of the formula as divisions round to zero.
+	 */
+	int nr_of_leap_years = (year == 0) ? 0 : ((year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400 + 1);
 
-	/* remove feb 29 from year 1,2,3 */
-	if (yr & 3) rem += (yr & 3) * 365 + (rem < 31 + 29);
+	/* Day-offset in a leap year */
+	int days = _accum_days_for_month[month] + day - 1;
 
-	/* base date. */
-	return (yr >> 2) * (365 + 365 + 365 + 366) + rem;
+	/* Account for the missing of the 29th of February in non-leap years */
+	if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
+
+	return year * 365 + nr_of_leap_years + days;
 }
 
 /** Functions used by the IncreaseDate function */
@@ -252,12 +279,12 @@
 	/* check if we reached the maximum year, decrement dates by a year */
 	} else if (_cur_year == MAX_YEAR + 1) {
 		Vehicle *v;
+		uint days_this_year;
 
 		_cur_year--;
-		_date -= 365;
-		FOR_ALL_VEHICLES(v) {
-			v->date_of_last_service -= 365;
-		}
+		days_this_year = IsLeapYear(_cur_year) ? 366 : 365;
+		_date -= days_this_year;
+		FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
 
 		/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
 		 *  all of them if the date is set back, else those messages will hang for ever */
--- a/date.h
+++ b/date.h
@@ -24,14 +24,16 @@
  * The offset in days from the '_date == 0' till
  * 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
  */
-#define DAYS_TILL_ORIGINAL_BASE_YEAR 0
+#define DAYS_TILL_ORIGINAL_BASE_YEAR (365 * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400)
 
 /* Temporary value to make transition to full past 2090 easier/more clear */
-#define BASE_YEAR 1920
+#define BASE_YEAR 0
 
 /* The absolute minimum & maximum years in OTTD */
-#define MIN_YEAR 1920
-#define MAX_YEAR 2090
+#define MIN_YEAR 0
+/* MAX_YEAR, nicely rounded value of the number of years that can
+ * be encoded in a single 32 bits date, about 2^31 / 366 years. */
+#define MAX_YEAR 5000000
 
 /* Year and Date are defined elsewhere */
 typedef uint8  Month;
--- a/engine.c
+++ b/engine.c
@@ -606,8 +606,10 @@
 }
 
 static const SaveLoad _engine_desc[] = {
-	SLE_VAR(Engine,intro_date,						SLE_UINT16),
-	SLE_VAR(Engine,age,										SLE_UINT16),
+	SLE_CONDVAR(Engine,intro_date,				SLE_FILE_U16 | SLE_VAR_I32,  0,  30),
+	SLE_CONDVAR(Engine,intro_date,				SLE_INT32, 31, SL_MAX_VERSION),
+	SLE_CONDVAR(Engine,age,								SLE_FILE_U16 | SLE_VAR_I32,  0,  30),
+	SLE_CONDVAR(Engine,age,								SLE_INT32, 31, SL_MAX_VERSION),
 	SLE_VAR(Engine,reliability,						SLE_UINT16),
 	SLE_VAR(Engine,reliability_spd_dec,		SLE_UINT16),
 	SLE_VAR(Engine,reliability_start,			SLE_UINT16),
--- a/engine.h
+++ b/engine.h
@@ -76,8 +76,8 @@
 typedef struct EngineInfo {
 	Date base_intro;
 	byte unk2;              ///< Carriages have the highest bit set in this one
-	byte lifelength;
-	byte base_life;
+	Year lifelength;
+	Year base_life;
 	byte railtype:4;
 	byte climates:4;
 	uint32 refit_mask;
--- a/genworld_gui.c
+++ b/genworld_gui.c
@@ -362,7 +362,7 @@
 		case 19: // Year text
 			WP(w, def_d).data_3 = START_DATE_QUERY;
 			SetDParam(0, _patches_newgame.starting_year);
-			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
 			break;
 		case 21: case 23: // Snow line buttons
 			/* Don't allow too fast scrolling */
@@ -629,7 +629,7 @@
 		case 15: // Year text
 			WP(w, def_d).data_3 = START_DATE_QUERY;
 			SetDParam(0, _patches_newgame.starting_year);
-			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
 			break;
 		case 17: case 19: // Height level buttons
 			/* Don't allow too fast scrolling */
--- a/industry.h
+++ b/industry.h
@@ -28,7 +28,7 @@
 	byte type;
 	byte owner;
 	byte color_map;
-	byte last_prod_year;
+	Year last_prod_year;
 	byte was_cargo_delivered;
 
 	uint16 index;
--- a/industry_cmd.c
+++ b/industry_cmd.c
@@ -1929,7 +1929,8 @@
 	SLE_VAR(Industry,type,						SLE_UINT8),
 	SLE_VAR(Industry,owner,						SLE_UINT8),
 	SLE_VAR(Industry,color_map,				SLE_UINT8),
-	SLE_VAR(Industry,last_prod_year,	SLE_UINT8),
+	SLE_CONDVAR(Industry, last_prod_year,	SLE_FILE_U8 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Industry, last_prod_year,	SLE_INT32, 31, SL_MAX_VERSION),
 	SLE_VAR(Industry,was_cargo_delivered,SLE_UINT8),
 
 	// reserve extra space in savegame here. (currently 32 bytes)
--- a/misc.c
+++ b/misc.c
@@ -268,7 +268,8 @@
 }
 
 static const SaveLoadGlobVarList _date_desc[] = {
-	    SLEG_VAR(_date,                  SLE_UINT16),
+	SLEG_CONDVAR(_date,                  SLE_FILE_U16 | SLE_VAR_U32,  0,  30),
+	SLEG_CONDVAR(_date,                  SLE_UINT32, 31, SL_MAX_VERSION),
 	    SLEG_VAR(_date_fract,            SLE_UINT16),
 	    SLEG_VAR(_tick_counter,          SLE_UINT16),
 	    SLEG_VAR(_vehicle_id_ctr_day,    SLE_UINT16),
--- a/misc_gui.c
+++ b/misc_gui.c
@@ -1714,7 +1714,7 @@
 	{SLE_BOOL,       0, STR_CHEAT_NO_JETCRASH,    &_cheats.no_jetcrash.value,     &_cheats.no_jetcrash.been_used,     NULL,                     0,  0},
 	{SLE_BOOL,       0, STR_CHEAT_SETUP_PROD,     &_cheats.setup_prod.value,      &_cheats.setup_prod.been_used,      NULL,                     0,  0},
 	{SLE_UINT8,      0, STR_CHEAT_SWITCH_CLIMATE, &_opt.landscape,                &_cheats.switch_climate.been_used,  &ClickChangeClimateCheat,-1,  4},
-	{SLE_UINT8,      0, STR_CHEAT_CHANGE_DATE,    &_cur_year,                     &_cheats.change_date.been_used,     &ClickChangeDateCheat,   -1,  1},
+	{SLE_INT32,      0, STR_CHEAT_CHANGE_DATE,    &_cur_year,                     &_cheats.change_date.been_used,     &ClickChangeDateCheat,   -1,  1},
 	{SLE_BOOL,       0, STR_CHEAT_ALLOW_CONVRAIL, &_cheats.elrail.value,          &_cheats.elrail.been_used,          &ClickAllowConvrail,      0,  0},
 };
 
--- a/network.h
+++ b/network.h
@@ -89,7 +89,7 @@
 typedef struct NetworkPlayerInfo {
 	char company_name[NETWORK_NAME_LENGTH];					// Company name
 	char password[NETWORK_PASSWORD_LENGTH];					// The password for the player
-	byte inaugurated_year;													// What year the company started in
+	Year inaugurated_year;													// What year the company started in
 	int64 company_value;														// The company value
 	int64 money;																		// The amount of money the company has
 	int64 income;																		// How much did the company earned last year
--- a/network_client.c
+++ b/network_client.c
@@ -300,7 +300,7 @@
 			return NETWORK_RECV_STATUS_CLOSE_QUERY;
 
 		NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
-		_network_player_info[current].inaugurated_year = NetworkRecv_uint8(MY_CLIENT, p);
+		_network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p);
 		_network_player_info[current].company_value = NetworkRecv_uint64(MY_CLIENT, p);
 		_network_player_info[current].money = NetworkRecv_uint64(MY_CLIENT, p);
 		_network_player_info[current].income = NetworkRecv_uint64(MY_CLIENT, p);
--- a/network_data.h
+++ b/network_data.h
@@ -18,9 +18,9 @@
 #define NETWORK_EMPTY_INDEX 0
 
 // What version of game-info do we use?
-#define NETWORK_GAME_INFO_VERSION 2
+#define NETWORK_GAME_INFO_VERSION 3
 // What version of company info is this?
-#define NETWORK_COMPANY_INFO_VERSION 3
+#define NETWORK_COMPANY_INFO_VERSION 4
 // What version of master-server-protocol do we use?
 #define NETWORK_MASTER_SERVER_VERSION 1
 
--- a/network_server.c
+++ b/network_server.c
@@ -95,7 +95,7 @@
 		NetworkSend_uint8 (p, player->index);
 
 		NetworkSend_string(p, _network_player_info[player->index].company_name);
-		NetworkSend_uint8 (p, _network_player_info[player->index].inaugurated_year);
+		NetworkSend_uint32(p, _network_player_info[player->index].inaugurated_year);
 		NetworkSend_uint64(p, _network_player_info[player->index].company_value);
 		NetworkSend_uint64(p, _network_player_info[player->index].money);
 		NetworkSend_uint64(p, _network_player_info[player->index].income);
--- a/network_udp.c
+++ b/network_udp.c
@@ -63,6 +63,10 @@
 
 	NetworkSend_uint8 (packet, NETWORK_GAME_INFO_VERSION);
 
+	/* NETWORK_GAME_INFO_VERSION = 3 */
+	NetworkSend_uint32(packet, _network_game_info.game_date);
+	NetworkSend_uint32(packet, _network_game_info.start_date);
+
 	/* NETWORK_GAME_INFO_VERSION = 2 */
 	NetworkSend_uint8 (packet, _network_game_info.companies_max);
 	NetworkSend_uint8 (packet, ActivePlayerCount());
@@ -76,8 +80,6 @@
 	NetworkSend_uint8 (packet, _network_game_info.clients_max);
 	NetworkSend_uint8 (packet, _network_game_info.clients_on);
 	NetworkSend_uint8 (packet, NetworkSpectatorCount());
-	NetworkSend_uint16(packet, _network_game_info.game_date);
-	NetworkSend_uint16(packet, _network_game_info.start_date);
 	NetworkSend_string(packet, _network_game_info.map_name);
 	NetworkSend_uint16(packet, _network_game_info.map_width);
 	NetworkSend_uint16(packet, _network_game_info.map_height);
@@ -114,6 +116,10 @@
 	/* Please observer the order. In the order in which packets are sent
 	 * they are to be received */
 	switch (game_info_version) {
+		case 3:
+			item->info.game_date     = NetworkRecv_uint32(&_udp_cs, p);
+			item->info.start_date    = NetworkRecv_uint32(&_udp_cs, p);
+			/* Fallthrough */
 		case 2:
 			item->info.companies_max = NetworkRecv_uint8(&_udp_cs, p);
 			item->info.companies_on = NetworkRecv_uint8(&_udp_cs, p);
@@ -127,8 +133,10 @@
 			item->info.clients_max   = NetworkRecv_uint8(&_udp_cs, p);
 			item->info.clients_on    = NetworkRecv_uint8(&_udp_cs, p);
 			item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p);
-			item->info.game_date     = NetworkRecv_uint16(&_udp_cs, p);
-			item->info.start_date    = NetworkRecv_uint16(&_udp_cs, p);
+			if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
+				item->info.game_date     = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+				item->info.start_date    = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+			}
 			NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name));
 			item->info.map_width     = NetworkRecv_uint16(&_udp_cs, p);
 			item->info.map_height    = NetworkRecv_uint16(&_udp_cs, p);
@@ -185,7 +193,7 @@
 		NetworkSend_uint8(packet, current);
 
 		NetworkSend_string(packet, _network_player_info[player->index].company_name);
-		NetworkSend_uint8 (packet, _network_player_info[player->index].inaugurated_year);
+		NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
 		NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
 		NetworkSend_uint64(packet, _network_player_info[player->index].money);
 		NetworkSend_uint64(packet, _network_player_info[player->index].income);
@@ -212,7 +220,7 @@
 				NetworkSend_uint8(packet, 1);
 				NetworkSend_string(packet, ci->client_name);
 				NetworkSend_string(packet, ci->unique_id);
-				NetworkSend_uint16(packet, ci->join_date);
+				NetworkSend_uint32(packet, ci->join_date);
 			}
 		}
 		/* Also check for the server itself */
@@ -222,7 +230,7 @@
 			NetworkSend_uint8(packet, 1);
 			NetworkSend_string(packet, ci->client_name);
 			NetworkSend_string(packet, ci->unique_id);
-			NetworkSend_uint16(packet, ci->join_date);
+			NetworkSend_uint32(packet, ci->join_date);
 		}
 
 		/* Indicates end of client list */
@@ -237,7 +245,7 @@
 			NetworkSend_uint8(packet, 1);
 			NetworkSend_string(packet, ci->client_name);
 			NetworkSend_string(packet, ci->unique_id);
-			NetworkSend_uint16(packet, ci->join_date);
+			NetworkSend_uint32(packet, ci->join_date);
 		}
 	}
 	/* Also check for the server itself */
@@ -247,7 +255,7 @@
 		NetworkSend_uint8(packet, 1);
 		NetworkSend_string(packet, ci->client_name);
 		NetworkSend_string(packet, ci->unique_id);
-		NetworkSend_uint16(packet, ci->join_date);
+		NetworkSend_uint32(packet, ci->join_date);
 	}
 
 	/* Indicates end of client list */
--- a/oldloader.c
+++ b/oldloader.c
@@ -702,7 +702,7 @@
 	OCL_SVAR(  OC_UINT8, Industry, type ),
 	OCL_SVAR(  OC_UINT8, Industry, owner ),
 	OCL_SVAR(  OC_UINT8, Industry, color_map ),
-	OCL_SVAR(  OC_UINT8, Industry, last_prod_year ),
+	OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Industry, last_prod_year ),
 	OCL_SVAR( OC_UINT16, Industry, counter ),
 	OCL_SVAR(  OC_UINT8, Industry, was_cargo_delivered ),
 
@@ -995,7 +995,7 @@
 		p->money64 = p->player_money = p->current_loan = 100000;
 
 	_player_colors[num] = p->player_color;
-	p->inaugurated_year = _old_inaugurated_year - BASE_YEAR;
+	p->inaugurated_year = _old_inaugurated_year;
 	if (p->location_of_house == 0xFFFF)
 		p->location_of_house = 0;
 
@@ -1122,7 +1122,7 @@
 	OCL_SVAR(  OC_UINT8, Vehicle, cur_order_index ),
 	OCL_SVAR(   OC_TILE, Vehicle, dest_tile ),
 	OCL_SVAR( OC_UINT16, Vehicle, load_unload_time_rem ),
-	OCL_SVAR( OC_UINT16, Vehicle, date_of_last_service ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
 	OCL_SVAR( OC_UINT16, Vehicle, service_interval ),
 	OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ),
 	OCL_SVAR(  OC_UINT8, Vehicle, tick_counter ),
@@ -1156,9 +1156,9 @@
 	OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_source ),
 	OCL_SVAR(  OC_UINT8, Vehicle, cargo_days ),
 
-	OCL_SVAR( OC_UINT16, Vehicle, age ),
-	OCL_SVAR( OC_UINT16, Vehicle, max_age ),
-	OCL_SVAR(  OC_UINT8, Vehicle, build_year ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, age ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, max_age ),
+	OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, build_year ),
 	OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, unitnumber ),
 
 	OCL_SVAR( OC_UINT16, Vehicle, engine_type ),
@@ -1259,8 +1259,8 @@
 
 static const OldChunks engine_chunk[] = {
 	OCL_SVAR( OC_UINT16, Engine, player_avail ),
-	OCL_SVAR( OC_UINT16, Engine, intro_date ),
-	OCL_SVAR( OC_UINT16, Engine, age ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, intro_date ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, age ),
 	OCL_SVAR( OC_UINT16, Engine, reliability ),
 	OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ),
 	OCL_SVAR( OC_UINT16, Engine, reliability_start ),
@@ -1375,7 +1375,7 @@
 static uint32 _old_cur_town_ctr;
 static const OldChunks main_chunk[] = {
 	OCL_ASSERT( 0 ),
-	OCL_VAR ( OC_UINT16,   1, &_date ),
+	OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_date ),
 	OCL_VAR ( OC_UINT16,   1, &_date_fract ),
 	OCL_NULL( 600 ),            // TextEffects
 	OCL_VAR ( OC_UINT32,   2, &_random_seeds[0] ),
--- a/openttd.c
+++ b/openttd.c
@@ -793,7 +793,7 @@
 				}
 			}
 			_generating_world = false;
-			_patches_newgame.starting_year = BASE_YEAR + _cur_year;
+			_patches_newgame.starting_year = ORIGINAL_BASE_YEAR + _cur_year;
 			// delete all stations owned by a player
 			DeleteAllPlayerStations();
 		} else {
@@ -1439,5 +1439,29 @@
 
 	if (!CheckSavegameVersion(27)) AfterLoadStations();
 
+	/* Time starts at 0 instead of 1920.
+	 * Account for this in older games by adding an offset */
+	if (CheckSavegameVersion(31)) {
+		Station *st;
+		Waypoint *wp;
+		Engine *e;
+		Player *player;
+		Industry *i;
+		Vehicle *v;
+
+		_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
+
+		FOR_ALL_STATIONS(st)    st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
+		FOR_ALL_WAYPOINTS(wp)   wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
+		FOR_ALL_ENGINES(e)      e->intro_date  += DAYS_TILL_ORIGINAL_BASE_YEAR;
+		FOR_ALL_PLAYERS(player) player->inaugurated_year += ORIGINAL_BASE_YEAR;
+		FOR_ALL_INDUSTRIES(i)   i->last_prod_year        += ORIGINAL_BASE_YEAR;
+
+		FOR_ALL_VEHICLES(v) {
+			v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR;
+			v->build_year += ORIGINAL_BASE_YEAR;
+		}
+	}
+
 	return true;
 }
--- a/openttd.h
+++ b/openttd.h
@@ -54,11 +54,11 @@
 
 enum {
 	INVALID_YEAR = -1,
-	INVALID_DATE = (uint16)-1,
+	INVALID_DATE = -1,
 };
 
-typedef int16  Year;
-typedef uint16 Date;
+typedef int32 Year;
+typedef int32 Date;
 
 
 enum GameModes {
--- a/player.h
+++ b/player.h
@@ -173,7 +173,7 @@
 
 	PlayerID share_owners[4];
 
-	byte inaugurated_year;
+	Year inaugurated_year;
 	byte num_valid_stat_ent;
 
 	byte quarters_of_bankrupcy;
--- a/players.c
+++ b/players.c
@@ -490,7 +490,7 @@
 	p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = OWNER_SPECTATOR;
 
 	p->avail_railtypes = GetPlayerRailtypes(p->index);
-	p->inaugurated_year = _cur_year - BASE_YEAR;
+	p->inaugurated_year = _cur_year;
 	p->face = Random();
 
 	/* Engine renewal settings */
@@ -1132,7 +1132,8 @@
 	SLE_CONDVAR(Player, location_of_house,     SLE_UINT32, 6, SL_MAX_VERSION),
 	SLE_CONDVAR(Player, last_build_coordinate, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 	SLE_CONDVAR(Player, last_build_coordinate, SLE_UINT32, 6, SL_MAX_VERSION),
-	SLE_VAR(Player,inaugurated_year,SLE_UINT8),
+	SLE_CONDVAR(Player, inaugurated_year,      SLE_FILE_U8  | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Player, inaugurated_year,      SLE_INT32, 31, SL_MAX_VERSION),
 
 	SLE_ARR(Player,share_owners,		SLE_UINT8, 4),
 
--- a/saveload.c
+++ b/saveload.c
@@ -30,7 +30,7 @@
 #include "variables.h"
 #include <setjmp.h>
 
-const uint16 SAVEGAME_VERSION = 30;
+const uint16 SAVEGAME_VERSION = 31;
 uint16 _sl_version;       /// the major savegame version identifier
 byte   _sl_minor_version; /// the minor savegame version, DO NOT USE!
 
--- a/settings.c
+++ b/settings.c
@@ -1207,7 +1207,7 @@
 	SDTG_BOOL("autoclean_companies",             S, 0, _network_autoclean_companies,  false,       STR_NULL, NULL),
 	 SDTG_VAR("autoclean_unprotected",SLE_UINT8, S, 0, _network_autoclean_unprotected,12, 0,  60,  STR_NULL, NULL),
 	 SDTG_VAR("autoclean_protected",  SLE_UINT8, S, 0, _network_autoclean_protected,  36, 0, 180,  STR_NULL, NULL),
-	 SDTG_VAR("restart_game_year",    SLE_INT16, S,D0, _network_restart_game_year,    0, MIN_YEAR, MAX_YEAR, STR_NULL, NULL),
+	 SDTG_VAR("restart_game_year",    SLE_INT32, S,D0, _network_restart_game_year,    0, MIN_YEAR, MAX_YEAR, STR_NULL, NULL),
 	 SDTG_END()
 };
 #endif /* ENABLE_NETWORK */
@@ -1321,9 +1321,9 @@
 	SDT_BOOL(Patches, same_industry_close,        0, 0, false,            STR_CONFIG_PATCHES_SAMEINDCLOSE,     NULL),
 	SDT_BOOL(Patches, bribe,                      0, 0,  true,            STR_CONFIG_PATCHES_BRIBE,            NULL),
 	 SDT_VAR(Patches, snow_line_height,SLE_UINT8, 0, 0,     7,   2,   13, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT,  NULL),
-	 SDT_VAR(Patches, colored_news_year,SLE_FILE_U32 | SLE_VAR_I16, 0,NC,  2000, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL),
-	 SDT_VAR(Patches, starting_year,    SLE_FILE_U32 | SLE_VAR_I16, 0,NC,  1950, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_STARTING_YEAR,NULL),
-	 SDT_VAR(Patches, ending_year,      SLE_FILE_U32 | SLE_VAR_I16,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_ENDING_YEAR,  NULL),
+	 SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC,  2000, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL),
+	 SDT_VAR(Patches, starting_year,    SLE_INT32, 0,NC,  1950, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_STARTING_YEAR,NULL),
+	 SDT_VAR(Patches, ending_year,      SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_ENDING_YEAR,  NULL),
 	SDT_BOOL(Patches, smooth_economy,             0, 0,  true,            STR_CONFIG_PATCHES_SMOOTH_ECONOMY,   NULL),
 	SDT_BOOL(Patches, allow_shares,               0, 0,  true,            STR_CONFIG_PATCHES_ALLOW_SHARES,     NULL),
 
@@ -1453,7 +1453,7 @@
 static const SettingDesc _currency_settings[] = {
 	SDT_VAR(CurrencySpec, rate,    SLE_UINT16, S, 0,  1, 0, 100, STR_NULL, NULL),
 	SDT_CHR(CurrencySpec, separator,           S, 0,        ".", STR_NULL, NULL),
-	SDT_VAR(CurrencySpec, to_euro, SLE_UINT16, S, 0,  0, 0,1000, STR_NULL, NULL),
+	SDT_VAR(CurrencySpec, to_euro,  SLE_INT32, S, 0,  0, 0,1000, STR_NULL, NULL),
 	SDT_STR(CurrencySpec, prefix,   SLE_STRBQ, S, 0,       NULL, STR_NULL, NULL),
 	SDT_STR(CurrencySpec, suffix,   SLE_STRBQ, S, 0, " credits", STR_NULL, NULL),
 	SDT_END()
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -3003,7 +3003,8 @@
 
 	// Was custom station class and id
 	SLE_CONDNULL(2, 3, 25),
-	SLE_CONDVAR(Station,build_date,        SLE_UINT16, 3, SL_MAX_VERSION),
+	SLE_CONDVAR(Station,build_date,        SLE_FILE_U16 | SLE_VAR_I32, 3, 30),
+	SLE_CONDVAR(Station,build_date,        SLE_INT32, 31, SL_MAX_VERSION),
 
 	SLE_CONDREF(Station,bus_stops,         REF_ROADSTOPS, 6, SL_MAX_VERSION),
 	SLE_CONDREF(Station,truck_stops,       REF_ROADSTOPS, 6, SL_MAX_VERSION),
--- a/vehicle.c
+++ b/vehicle.c
@@ -2202,17 +2202,22 @@
 
 	SLE_REF(Vehicle,orders,						REF_ORDER),
 
-	SLE_VAR(Vehicle,age,							SLE_UINT16),
-	SLE_VAR(Vehicle,max_age,					SLE_UINT16),
-	SLE_VAR(Vehicle,date_of_last_service,SLE_UINT16),
-	SLE_VAR(Vehicle,service_interval,	SLE_UINT16),
+	SLE_CONDVAR(Vehicle,age,					SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,age,					SLE_INT32, 31, SL_MAX_VERSION),
+	SLE_CONDVAR(Vehicle,max_age,			SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,max_age,			SLE_INT32, 31, SL_MAX_VERSION),
+	SLE_CONDVAR(Vehicle,date_of_last_service,	SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,date_of_last_service,	SLE_INT32, 31, SL_MAX_VERSION),
+	SLE_CONDVAR(Vehicle,service_interval,			SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,service_interval,			SLE_INT32, 31, SL_MAX_VERSION),
 	SLE_VAR(Vehicle,reliability,			SLE_UINT16),
 	SLE_VAR(Vehicle,reliability_spd_dec,SLE_UINT16),
 	SLE_VAR(Vehicle,breakdown_ctr,		SLE_UINT8),
 	SLE_VAR(Vehicle,breakdown_delay,	SLE_UINT8),
 	SLE_VAR(Vehicle,breakdowns_since_last_service,	SLE_UINT8),
 	SLE_VAR(Vehicle,breakdown_chance,	SLE_UINT8),
-	SLE_VAR(Vehicle,build_year,				SLE_UINT8),
+	SLE_CONDVAR(Vehicle,build_year,		SLE_FILE_U8 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,build_year,		SLE_INT32, 31, SL_MAX_VERSION),
 
 	SLE_VAR(Vehicle,load_unload_time_rem,	SLE_UINT16),
 
@@ -2362,8 +2367,8 @@
 	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, station), SLE_UINT16, 5, SL_MAX_VERSION),
 
 	SLE_VAR(Vehicle,cur_image,				SLE_UINT16),
-	SLE_VAR(Vehicle,age,							SLE_UINT16),
-
+	SLE_CONDVAR(Vehicle,age,					SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
+	SLE_CONDVAR(Vehicle,age,					SLE_INT32, 31, SL_MAX_VERSION),
 	SLE_VAR(Vehicle,tick_counter,			SLE_UINT8),
 
 	SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleDisaster,image_override),	SLE_UINT16),
--- a/vehicle.h
+++ b/vehicle.h
@@ -208,8 +208,8 @@
 	VehicleID next_hash;
 
 	// Related to age and service time
-	uint16 age;				// Age in days
-	uint16 max_age;		// Maximum age
+	Date age;     // Age in days
+	Date max_age; // Maximum age
 	Date date_of_last_service;
 	Date service_interval;
 	uint16 reliability;
@@ -218,7 +218,7 @@
 	byte breakdown_delay;
 	byte breakdowns_since_last_service;
 	byte breakdown_chance;
-	byte build_year;
+	Year build_year;
 
 	bool leave_depot_instantly;	// NOSAVE: stores if the vehicle needs to leave the depot it just entered. Used by autoreplace
 
--- a/waypoint.c
+++ b/waypoint.c
@@ -408,7 +408,8 @@
 	SLE_VAR(Waypoint, string, SLE_UINT16),
 	SLE_VAR(Waypoint, deleted, SLE_UINT8),
 
-	SLE_CONDVAR(Waypoint, build_date, SLE_UINT16,  3, SL_MAX_VERSION),
+	SLE_CONDVAR(Waypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30),
+	SLE_CONDVAR(Waypoint, build_date, SLE_INT32,  31, SL_MAX_VERSION),
 	SLE_CONDVAR(Waypoint, localidx,   SLE_UINT8,   3, SL_MAX_VERSION),
 	SLE_CONDVAR(Waypoint, grfid,      SLE_UINT32, 17, SL_MAX_VERSION),