misc.c
changeset 0 29654efe3188
child 105 44e894da0fef
equal deleted inserted replaced
-1:000000000000 0:29654efe3188
       
     1 #include "stdafx.h"
       
     2 #include "ttd.h"
       
     3 #include "vehicle.h"
       
     4 #include "gfx.h"
       
     5 #include "assert.h"
       
     6 #include "saveload.h"
       
     7 
       
     8 extern void StartupEconomy();
       
     9 extern void InitNewsItemStructs();
       
    10 
       
    11 static uint32 _random_seed_3, _random_seed_4;
       
    12 
       
    13 byte _name_array[512][32];
       
    14 
       
    15 static INLINE uint32 ROR(uint32 x, int n)
       
    16 {
       
    17 	return (x >> n) + (x << ((sizeof(x)*8)-n));
       
    18 }
       
    19 
       
    20 
       
    21 uint32 Random()
       
    22 {
       
    23 	uint32 t = _random_seed_2;
       
    24 	uint32 s = _random_seed_1;
       
    25 	_random_seed_1 = s + ROR(t ^ 0x1234567F, 7);
       
    26 	return _random_seed_2 = ROR(s, 3);
       
    27 }
       
    28 
       
    29 uint RandomRange(uint max)
       
    30 {
       
    31 	return (uint16)Random() * max >> 16;
       
    32 }
       
    33 
       
    34 uint32 InteractiveRandom()
       
    35 {
       
    36 	uint32 t = _random_seed_4;
       
    37 	uint32 s = _random_seed_3;
       
    38 	_random_seed_3 = s + ROR(t ^ 0x1234567F, 7);
       
    39 	return _random_seed_4 = ROR(s, 3);
       
    40 }
       
    41 
       
    42 void memswap(void *a, void *b, size_t size) {
       
    43 	void *c = alloca(size);
       
    44 	memcpy(c, a, size);
       
    45 	memcpy(a, b, size);
       
    46 	memcpy(b, c, size);
       
    47 }
       
    48 
       
    49 void SetDate(uint date)
       
    50 {
       
    51 	YearMonthDay ymd;
       
    52 	ConvertDayToYMD(&ymd, _date = date);
       
    53 	_cur_year = ymd.year;
       
    54 	_cur_month = ymd.month;
       
    55 }
       
    56 
       
    57 void InitializeClearLand();
       
    58 void InitializeRail();
       
    59 void InitializeRailGui();
       
    60 void InitializeRoad();
       
    61 void InitializeRoadGui();
       
    62 void InitializeAirportGui();
       
    63 void InitializeDock();
       
    64 void InitializeDockGui();
       
    65 void InitializeIndustries();
       
    66 void InitializeLandscape();
       
    67 void InitializeTowns();
       
    68 void InitializeTrees();
       
    69 void InitializeStations();
       
    70 void InitializeNameMgr();
       
    71 void InitializePlayers();
       
    72 void InitializeCheats();
       
    73 
       
    74 void GenerateLandscape();
       
    75 void GenerateClearTile();
       
    76 
       
    77 void GenerateIndustries();
       
    78 void GenerateUnmovables();
       
    79 void GenerateTowns();
       
    80 
       
    81 void StartupPlayers();
       
    82 void StartupEngines();
       
    83 void StartupDisasters();
       
    84 void GenerateTrees();
       
    85 
       
    86 void ConvertGroundTilesIntoWaterTiles();
       
    87 
       
    88 void InitializeGame()
       
    89 {
       
    90 	SetObjectToPlace(1, 0, 0, 0);
       
    91 
       
    92 	_pause = 0;
       
    93 	_fast_forward = 0;
       
    94 	_tick_counter = 0;
       
    95 	_date_fract = 0;
       
    96 	_cur_tileloop_tile = 0;
       
    97 	_vehicle_id_ctr_day = 0;
       
    98 	
       
    99 	{
       
   100 		uint starting = ConvertIntDate(_patches.starting_date);
       
   101 		if ( starting == (uint)-1) starting = 10958;
       
   102 		SetDate(starting);
       
   103 	}
       
   104 
       
   105 	InitializeVehicles();
       
   106 	_backup_orders_tile = 0;
       
   107 
       
   108 	InitNewsItemStructs();
       
   109 	InitializeLandscape();
       
   110 	InitializeClearLand();
       
   111 	InitializeRail();
       
   112 	InitializeRailGui();
       
   113 	InitializeRoad();
       
   114 	InitializeRoadGui();
       
   115 	InitializeAirportGui();
       
   116 	InitializeDock();
       
   117 	InitializeDockGui();
       
   118 	InitializeTowns();
       
   119 	InitializeTrees();
       
   120 	InitializeStations();
       
   121 	InitializeIndustries();
       
   122 	
       
   123 	InitializeNameMgr();
       
   124 	InitializeTrains();
       
   125 
       
   126 	InitializePlayers();
       
   127 	InitializeCheats();
       
   128 
       
   129 	InitTextEffects();
       
   130 	InitializeAnimatedTiles();
       
   131 
       
   132 	InitializeLandscapeVariables(false);
       
   133 
       
   134 	ResetObjectToPlace();
       
   135 }
       
   136 
       
   137 void GenerateWorld(int mode)
       
   138 {
       
   139 	int i;
       
   140 
       
   141 	_generating_world = true;
       
   142 	InitializeGame();
       
   143 	SetObjectToPlace(1, 0, 0, 0);
       
   144 
       
   145 	// Must start economy early because of the costs.
       
   146 	StartupEconomy();
       
   147 
       
   148 	// Don't generate landscape items when in the scenario editor.
       
   149 	if (mode == 1) {
       
   150 		// empty world in scenario editor
       
   151 		ConvertGroundTilesIntoWaterTiles();
       
   152 	} else {
       
   153 		GenerateLandscape();
       
   154 		GenerateClearTile();
       
   155 		
       
   156 		// only generate towns, tree and industries in newgame mode.
       
   157 		if (mode == 0) {
       
   158 			GenerateTowns();
       
   159 			GenerateTrees();
       
   160 			GenerateIndustries();
       
   161 			GenerateUnmovables();
       
   162 		}
       
   163 	}
       
   164 
       
   165 	// These are probably pointless when inside the scenario editor.	
       
   166 	StartupPlayers();
       
   167 	StartupEngines();
       
   168 	StartupDisasters();
       
   169 	_generating_world = false;
       
   170 
       
   171 	// No need to run the tile loop in the scenario editor.
       
   172 	if (mode != 1) {
       
   173 		for(i=0x500; i!=0; i--)
       
   174 			RunTileLoop();
       
   175 	}
       
   176 
       
   177 	ResetObjectToPlace();
       
   178 }
       
   179 
       
   180 void DeleteName(StringID id)
       
   181 {
       
   182 	if ((id & 0xF800) == 0x7800) {
       
   183 		memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF]));
       
   184 	}
       
   185 }
       
   186 
       
   187 byte *GetName(int id, byte *buff)
       
   188 {
       
   189 	byte *b;
       
   190 
       
   191 	if (id & 0x600) {
       
   192 		if (id & 0x200) {
       
   193 			if (id & 0x400) {
       
   194 				GetParamInt32();
       
   195 				GetParamUint16();
       
   196 			} else {
       
   197 				GetParamUint16();
       
   198 			}
       
   199 		} else {
       
   200 			GetParamInt32();
       
   201 		}
       
   202 	}
       
   203 
       
   204 	b = _name_array[(id&~0x600)];
       
   205 	while ((*buff++ = *b++) != 0);
       
   206 
       
   207 	return buff - 1;
       
   208 }
       
   209 
       
   210 
       
   211 void InitializeCheats()
       
   212 {
       
   213 	memset(&_cheats, 0, sizeof(Cheats)); 
       
   214 }
       
   215 
       
   216 
       
   217 void InitializeNameMgr()
       
   218 {
       
   219 	memset(_name_array, 0, sizeof(_name_array));
       
   220 }
       
   221 
       
   222 StringID AllocateName(const byte *name, byte skip)
       
   223 {
       
   224 	int free_item = -1;
       
   225 	const byte *names;
       
   226 	byte *dst;
       
   227 	int i;
       
   228 
       
   229 	names = &_name_array[0][0];
       
   230 
       
   231 	for(i=0; i!=512; i++,names+=sizeof(_name_array[0])) {
       
   232 		if (names[0] == 0) {
       
   233 			if (free_item == -1)
       
   234 				free_item = i;
       
   235 		} else {
       
   236 			if (str_eq(names, name)) {
       
   237 				_error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY;
       
   238 				return 0;
       
   239 			}
       
   240 		}
       
   241 	}
       
   242 
       
   243 	if (free_item < 0) {
       
   244 		_error_message = STR_0131_TOO_MANY_NAMES_DEFINED;
       
   245 		return 0;
       
   246 	}
       
   247 
       
   248 	dst=_name_array[free_item];
       
   249 
       
   250 	for(i=0; (dst[i] = name[i]) != 0 && ++i != 32; ) {}
       
   251 	dst[31] = 0;
       
   252 		
       
   253 	return free_item | 0x7800 | (skip << 8);
       
   254 }
       
   255 
       
   256 const TileIndexDiff _tileoffs_by_dir[4] = {
       
   257 	TILE_XY(-1, 0),
       
   258 	TILE_XY(0, 1),
       
   259 	TILE_XY(1, 0),
       
   260 	TILE_XY(0, -1),
       
   261 };
       
   262 
       
   263 
       
   264 #define M(a,b) ((a<<5)|b)
       
   265 static const uint16 _month_date_from_year_day[] = {
       
   266 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),
       
   267 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),
       
   268 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),
       
   269 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),
       
   270 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),
       
   271 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),
       
   272 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),
       
   273 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),
       
   274 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),
       
   275 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),
       
   276 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),
       
   277 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),
       
   278 };
       
   279 #undef M
       
   280 
       
   281 enum {
       
   282 	ACCUM_JAN = 0,
       
   283 	ACCUM_FEB = ACCUM_JAN + 31,
       
   284 	ACCUM_MAR = ACCUM_FEB + 29,
       
   285 	ACCUM_APR = ACCUM_MAR + 31,
       
   286 	ACCUM_MAY = ACCUM_APR + 30,
       
   287 	ACCUM_JUN = ACCUM_MAY + 31,
       
   288 	ACCUM_JUL = ACCUM_JUN + 30,
       
   289 	ACCUM_AUG = ACCUM_JUL + 31,
       
   290 	ACCUM_SEP = ACCUM_AUG + 31,
       
   291 	ACCUM_OCT = ACCUM_SEP + 30,
       
   292 	ACCUM_NOV = ACCUM_OCT + 31,
       
   293 	ACCUM_DEC = ACCUM_NOV + 30,
       
   294 };
       
   295 
       
   296 static const uint16 _accum_days_for_month[] = {
       
   297 	ACCUM_JAN,ACCUM_FEB,ACCUM_MAR,ACCUM_APR,
       
   298 	ACCUM_MAY,ACCUM_JUN,ACCUM_JUL,ACCUM_AUG,
       
   299 	ACCUM_SEP,ACCUM_OCT,ACCUM_NOV,ACCUM_DEC,
       
   300 };
       
   301 
       
   302 
       
   303 void ConvertDayToYMD(YearMonthDay *ymd, uint16 date)
       
   304 {
       
   305 	uint yr = date / (365+365+365+366);
       
   306 	uint rem = date % (365+365+365+366);
       
   307 	uint x;
       
   308 
       
   309 	yr *= 4;
       
   310 
       
   311 	if (rem >= 366) {
       
   312 		rem--;
       
   313 		do {
       
   314 			rem -= 365;
       
   315 			yr++;
       
   316 		} while (rem >= 365);
       
   317 		if (rem >= 31+28) rem++;
       
   318 	}
       
   319 
       
   320 	ymd->year = yr;
       
   321 		
       
   322 	x = _month_date_from_year_day[rem];
       
   323 	ymd->month = x >> 5;
       
   324 	ymd->day = x & 0x1F;
       
   325 }
       
   326 
       
   327 // year is a number between 0..?
       
   328 // month is a number between 0..11
       
   329 // day is a number between 1..31
       
   330 uint ConvertYMDToDay(uint year, uint month, uint day)
       
   331 {
       
   332 	uint rem;
       
   333 	
       
   334 	// day in the year
       
   335 	rem = _accum_days_for_month[month] + day - 1;
       
   336 
       
   337 	// remove feb 29 from year 1,2,3
       
   338 	if (year & 3) rem += (year & 3) * 365 + (rem < 31+29);
       
   339 
       
   340 	// base date.
       
   341 	return (year >> 2) * (365+365+365+366) + rem;
       
   342 }
       
   343 
       
   344 // convert a date on the form
       
   345 // 1920 - 2090
       
   346 // 192001 - 209012
       
   347 // 19200101 - 20901231
       
   348 // or if > 2090 and below 65536, treat it as a daycount
       
   349 // returns -1 if no conversion was possible
       
   350 uint ConvertIntDate(uint date)
       
   351 {
       
   352 	uint year, month = 0, day = 1;
       
   353 
       
   354 	if (IS_INT_INSIDE(date, 1920, 2090 + 1)) {
       
   355 		year = date - 1920;
       
   356 	} else if (IS_INT_INSIDE(date, 192001, 209012+1)) {
       
   357 		month = date % 100 - 1;	
       
   358 		year = date / 100 - 1920;
       
   359 	} else if (IS_INT_INSIDE(date, 19200101, 20901231+1)) {
       
   360 		day = date % 100; date /= 100;
       
   361 		month = date % 100 - 1;	
       
   362 		year = date / 100 - 1920;
       
   363 	} else if (IS_INT_INSIDE(date, 2091, 65536))
       
   364 		return date;
       
   365 	else
       
   366 		return (uint)-1;
       
   367 
       
   368 	// invalid ranges?
       
   369 	if (month >= 12 || !IS_INT_INSIDE(day, 1, 31+1)) return (uint)-1;
       
   370 
       
   371 	return ConvertYMDToDay(year, month, day);
       
   372 }
       
   373 
       
   374 typedef struct LandscapePredefVar {
       
   375 	StringID names[NUM_CARGO];
       
   376 	byte weights[NUM_CARGO];
       
   377 	StringID sprites[NUM_CARGO];
       
   378 
       
   379 	uint16 initial_cargo_payment[NUM_CARGO];
       
   380 	byte transit_days_table_1[NUM_CARGO];
       
   381 	byte transit_days_table_2[NUM_CARGO];
       
   382 
       
   383 	byte railwagon_by_cargo[3][NUM_CARGO];
       
   384 
       
   385 	byte road_veh_by_cargo_start[NUM_CARGO];
       
   386 	byte road_veh_by_cargo_count[NUM_CARGO];
       
   387 } LandscapePredefVar;
       
   388 
       
   389 #include "table/landscape_const.h"
       
   390 
       
   391 
       
   392 // Calculate constants that depend on the landscape type.
       
   393 void InitializeLandscapeVariables(bool only_constants)
       
   394 {
       
   395 	const LandscapePredefVar *lpd;
       
   396 	int i;
       
   397 	StringID str;
       
   398 
       
   399 	lpd = &_landscape_predef_var[_opt.landscape];
       
   400 
       
   401 	memcpy(_cargoc.ai_railwagon, lpd->railwagon_by_cargo, sizeof(lpd->railwagon_by_cargo));
       
   402 	memcpy(_cargoc.ai_roadveh_start, lpd->road_veh_by_cargo_start,sizeof(lpd->road_veh_by_cargo_start));
       
   403 	memcpy(_cargoc.ai_roadveh_count, lpd->road_veh_by_cargo_count,sizeof(lpd->road_veh_by_cargo_count));
       
   404 
       
   405 	for(i=0; i!=NUM_CARGO; i++) {
       
   406 		_cargoc.sprites[i] = lpd->sprites[i];
       
   407 		
       
   408 		str = lpd->names[i];
       
   409 		_cargoc.names_s[i] = str;
       
   410 		_cargoc.names_p[i] = (str += 0x20);
       
   411 		_cargoc.names_long_s[i] = (str += 0x20);
       
   412 		_cargoc.names_long_p[i] = (str += 0x20);
       
   413 		_cargoc.names_short[i] = (str += 0x20);
       
   414 		_cargoc.weights[i] = lpd->weights[i];
       
   415 		
       
   416 		if (!only_constants) {
       
   417 			_cargo_payment_rates[i] = lpd->initial_cargo_payment[i];
       
   418 			_cargo_payment_rates_frac[i] = 0;
       
   419 		}
       
   420 
       
   421 		_cargoc.transit_days_1[i] = lpd->transit_days_table_1[i];
       
   422 		_cargoc.transit_days_2[i] = lpd->transit_days_table_2[i];
       
   423 	}
       
   424 }
       
   425 
       
   426 // distance in Manhattan metric
       
   427 uint GetTileDist(TileIndex xy1, TileIndex xy2)
       
   428 {
       
   429 	return myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)) + 
       
   430 				myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2));
       
   431 }
       
   432 
       
   433 // maximum distance in x _or_ y
       
   434 uint GetTileDist1D(TileIndex xy1, TileIndex xy2)
       
   435 {
       
   436 	return max(myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)),
       
   437 						 myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)));
       
   438 }
       
   439 
       
   440 uint GetTileDist1Db(TileIndex xy1, TileIndex xy2)
       
   441 {
       
   442 	int a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2));
       
   443 	int b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2));
       
   444 
       
   445 	if (a > b)
       
   446 		return a*2+b;
       
   447 	else
       
   448 		return b*2+a;
       
   449 }
       
   450 
       
   451 uint GetTileDistAdv(TileIndex xy1, TileIndex xy2)
       
   452 {
       
   453 	uint a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2));
       
   454 	uint b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2));
       
   455 	return a*a+b*b;
       
   456 }
       
   457 
       
   458 bool CheckDistanceFromEdge(TileIndex tile, uint distance)
       
   459 {
       
   460 	return IS_INT_INSIDE(GET_TILE_X(tile), distance, TILE_X_MAX + 1 - distance) &&
       
   461 			IS_INT_INSIDE(GET_TILE_Y(tile), distance, TILE_Y_MAX + 1 - distance);
       
   462 }
       
   463 
       
   464 void OnNewDay_Train(Vehicle *v);
       
   465 void OnNewDay_RoadVeh(Vehicle *v);
       
   466 void OnNewDay_Aircraft(Vehicle *v);
       
   467 void OnNewDay_Ship(Vehicle *v);
       
   468 void OnNewDay_EffectVehicle(Vehicle *v) { /* empty */ }
       
   469 void OnNewDay_DisasterVehicle(Vehicle *v);
       
   470 
       
   471 typedef void OnNewVehicleDayProc(Vehicle *v);
       
   472 
       
   473 static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = {
       
   474 	OnNewDay_Train,
       
   475 	OnNewDay_RoadVeh,
       
   476 	OnNewDay_Ship,
       
   477 	OnNewDay_Aircraft,
       
   478 	OnNewDay_EffectVehicle,
       
   479 	OnNewDay_DisasterVehicle,
       
   480 };
       
   481 
       
   482 void EnginesDailyLoop();
       
   483 void DisasterDailyLoop();
       
   484 void PlayersMonthlyLoop();
       
   485 void EnginesMonthlyLoop();
       
   486 void TownsMonthlyLoop();
       
   487 void IndustryMonthlyLoop();
       
   488 void StationMonthlyLoop();
       
   489 
       
   490 void PlayersYearlyLoop();
       
   491 void TrainsYearlyLoop();
       
   492 void RoadVehiclesYearlyLoop();
       
   493 void AircraftYearlyLoop();
       
   494 void ShipsYearlyLoop();
       
   495 
       
   496 void CheckpointsDailyLoop();
       
   497 
       
   498 
       
   499 static const uint16 _autosave_months[] = {
       
   500 	0, // never
       
   501 	0xFFF, // every month
       
   502 	0x249, // every 3 months
       
   503 	0x041, // every 6 months
       
   504 	0x001, // every 12 months
       
   505 };
       
   506 
       
   507 void IncreaseDate()
       
   508 {
       
   509 	int i,ctr,t;
       
   510 	YearMonthDay ymd;
       
   511 
       
   512 	if (_game_mode == GM_MENU) {
       
   513 		_tick_counter++;
       
   514 		return;
       
   515 	}
       
   516 
       
   517 	/*if the day changed, call the vehicle event but only update a part of the vehicles
       
   518 		old max was i!= 12. But with that and a bigger number of vehicles (2560), per day only
       
   519 		a part of it could be done, namely: function called max_size date_fract (uint16) / 885 x 12 ==>
       
   520 		65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd
       
   521 		eg. aged.
       
   522 		So new code updates it for max vehicles.
       
   523 		(NUM_VEHICLES / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too)
       
   524 		max size of _date_fract / 885 (added each tick) is number of times before ctr is reset.
       
   525 		Calculation might look complicated, but compiler just replaces it with 35, so that's ok
       
   526 	*/
       
   527 
       
   528 	ctr = _vehicle_id_ctr_day;
       
   529 	for(i=0; i!=(NUM_VEHICLES / ((1<<sizeof(_date_fract)*8) / 885)) + 1 && ctr != lengthof(_vehicles); i++) {
       
   530 		Vehicle *v = &_vehicles[ctr++];
       
   531 		if ((t=v->type) != 0)
       
   532 			_on_new_vehicle_day_proc[t - 0x10](v);
       
   533 	}
       
   534 	_vehicle_id_ctr_day = ctr;
       
   535 
       
   536 	/* increase day, and check if a new day is there? */
       
   537 	_tick_counter++;
       
   538 	
       
   539 	if ( (_date_fract += 885) >= 885)
       
   540 		return;
       
   541 
       
   542 	/* yeah, increse day counter and call various daily loops */
       
   543 	_date++;
       
   544 
       
   545 	_vehicle_id_ctr_day = 0;
       
   546 
       
   547 	DisasterDailyLoop();
       
   548 	CheckpointsDailyLoop();
       
   549 
       
   550 	if (_game_mode != GM_MENU) {
       
   551 		InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
       
   552 		EnginesDailyLoop();
       
   553 	}
       
   554 
       
   555 	/* check if we entered a new month? */
       
   556 	ConvertDayToYMD(&ymd, _date);
       
   557 	if ((byte)ymd.month == _cur_month)
       
   558 		return;
       
   559 	_cur_month = ymd.month;
       
   560 
       
   561 //	printf("Month %d, %X\n", ymd.month, _random_seed_1);
       
   562 
       
   563 	/* yes, call various monthly loops */
       
   564 	if (_game_mode != GM_MENU) {
       
   565 		if (HASBIT(_autosave_months[_opt.autosave], _cur_month)) {
       
   566 			_do_autosave = true;
       
   567 			RedrawAutosave();
       
   568 		}
       
   569 
       
   570 		PlayersMonthlyLoop();
       
   571 		EnginesMonthlyLoop();
       
   572 		TownsMonthlyLoop();
       
   573 		IndustryMonthlyLoop();
       
   574 		StationMonthlyLoop();
       
   575 	}
       
   576 
       
   577 	/* check if we entered a new year? */
       
   578 	if ((byte)ymd.year == _cur_year)
       
   579 		return;
       
   580 	_cur_year = ymd.year;
       
   581 
       
   582 	/* yes, call various yearly loops */ 
       
   583 
       
   584 	PlayersYearlyLoop();
       
   585 	TrainsYearlyLoop();
       
   586 	RoadVehiclesYearlyLoop();
       
   587 	AircraftYearlyLoop();
       
   588 	ShipsYearlyLoop();
       
   589 
       
   590 	/* check if we reached 2090, that's the maximum year. */
       
   591 	if (_cur_year == 171) {
       
   592 		_cur_year = 170;
       
   593 		_date = 62093;
       
   594 	}
       
   595 
       
   596 	if (_patches.auto_euro)
       
   597 		CheckSwitchToEuro();
       
   598 
       
   599 	/* XXX: check if year 2050 was reached */
       
   600 }
       
   601 
       
   602 int FindFirstBit(uint32 x)
       
   603 {
       
   604 	int i = 0;
       
   605 	assert(x != 0);
       
   606 	for(;!(x&1);i++,x>>=1);
       
   607 	return i;
       
   608 }
       
   609 
       
   610 
       
   611 extern uint SafeTileAdd(uint tile, int add, const char *exp, const char *file, int line)
       
   612 {
       
   613 	int x = GET_TILE_X(tile) + (signed char)(add & 0xFF);
       
   614 	int y = GET_TILE_Y(tile) + ((((0x8080 + add)>>8) & 0xFF) - 0x80);
       
   615 
       
   616 	if (x < 0 || y < 0 || x >= TILES_X || y >= TILES_Y) {
       
   617 		char buf[512];
       
   618 
       
   619 		sprintf(buf, "TILE_ADD(%s) when adding 0x%.4X and %d failed", exp, tile, add);
       
   620 #if !defined(_DEBUG) || !defined(_MSC_VER)
       
   621 		printf("%s\n", buf);
       
   622 #else
       
   623 		_assert(buf, (char*)file, line);
       
   624 #endif
       
   625 	}
       
   626 
       
   627 	assert(TILE_XY(x,y) == TILE_MASK(tile + add));
       
   628 
       
   629 	return TILE_XY(x,y);
       
   630 }
       
   631 
       
   632 static void Save_NAME()
       
   633 {
       
   634 	int i;
       
   635 	byte *b = _name_array[0];
       
   636 
       
   637 	for(i=0; i!=lengthof(_name_array); i++,b+=sizeof(_name_array[0])) {
       
   638 		if (*b) {
       
   639 			SlSetArrayIndex(i);
       
   640 			SlArray(b, strlen(b), SLE_UINT8);
       
   641 		}	
       
   642 	}
       
   643 }
       
   644 
       
   645 static void Load_NAME()
       
   646 {
       
   647 	int index;
       
   648 	
       
   649 	while ((index = SlIterateArray()) != -1) {
       
   650 		SlArray(_name_array[index],SlGetFieldLength(),SLE_UINT8);
       
   651 	}
       
   652 }
       
   653 
       
   654 static const byte _game_opt_desc[] = {
       
   655 	// added a new difficulty option (town attitude) in version 4
       
   656 	SLE_CONDARR(GameOptions,diff,						SLE_FILE_I16 | SLE_VAR_I32, 17, 0, 3),
       
   657 	SLE_CONDARR(GameOptions,diff,						SLE_FILE_I16 | SLE_VAR_I32, 18, 4, 255),
       
   658 	SLE_VAR(GameOptions,diff_level,			SLE_UINT8),
       
   659 	SLE_VAR(GameOptions,currency,				SLE_UINT8),
       
   660 	SLE_VAR(GameOptions,kilometers,			SLE_UINT8),
       
   661 	SLE_VAR(GameOptions,town_name,			SLE_UINT8),
       
   662 	SLE_VAR(GameOptions,landscape,			SLE_UINT8),
       
   663 	SLE_VAR(GameOptions,snow_line,			SLE_UINT8),
       
   664 	SLE_VAR(GameOptions,autosave,				SLE_UINT8),
       
   665 	SLE_VAR(GameOptions,road_side,			SLE_UINT8),
       
   666 	SLE_END()
       
   667 };
       
   668 
       
   669 // Save load game options
       
   670 static void SaveLoad_OPTS()
       
   671 {
       
   672 	SlObject(&_opt, _game_opt_desc);	
       
   673 }
       
   674 
       
   675 
       
   676 static const SaveLoadGlobVarList _date_desc[] = {
       
   677 	{&_date, 										SLE_UINT16, 0, 255},
       
   678 	{&_date_fract, 							SLE_UINT16, 0, 255},
       
   679 	{&_tick_counter, 						SLE_UINT16, 0, 255},
       
   680 	{&_vehicle_id_ctr_day, 			SLE_UINT16, 0, 255},
       
   681 	{&_age_cargo_skip_counter, 	SLE_UINT8,	0, 255},
       
   682 	{&_avail_aircraft, 					SLE_UINT8,	0, 255},
       
   683 	{&_cur_tileloop_tile, 			SLE_UINT16, 0, 255},
       
   684 	{&_disaster_delay, 					SLE_UINT16, 0, 255},
       
   685 	{&_station_tick_ctr, 				SLE_UINT16, 0, 255},
       
   686 	{&_random_seed_1, 					SLE_UINT32, 0, 255},
       
   687 	{&_random_seed_2, 					SLE_UINT32, 0, 255},
       
   688 	{&_cur_town_ctr, 						SLE_UINT8,	0, 255},
       
   689 	{&_cur_player_tick_index, 	SLE_FILE_U8 | SLE_VAR_UINT, 0, 255},
       
   690 	{&_next_competitor_start, 	SLE_FILE_U16 | SLE_VAR_UINT, 0, 255},
       
   691 	{&_trees_tick_ctr, 					SLE_UINT8,	0, 255},
       
   692 	{&_pause, 									SLE_UINT8,	4, 255},
       
   693 	{NULL,0}
       
   694 };
       
   695 
       
   696 // Save load date related variables as well as persistent tick counters
       
   697 // XXX: currently some unrelated stuff is just put here
       
   698 static void SaveLoad_DATE()
       
   699 {
       
   700 	SlGlobList(_date_desc);
       
   701 }
       
   702 
       
   703 
       
   704 static const SaveLoadGlobVarList _view_desc[] = {
       
   705 	{&_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_INT, 0, 255},
       
   706 	{&_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_INT, 0, 255},
       
   707 	{&_saved_scrollpos_zoom, SLE_UINT8, 0, 255},
       
   708 	{NULL,0}
       
   709 };
       
   710 
       
   711 static void SaveLoad_VIEW()
       
   712 {
       
   713 	SlGlobList(_view_desc);
       
   714 }
       
   715 
       
   716 static void SaveLoad_MAPT() {
       
   717   SlArray(_map_type_and_height, lengthof(_map_type_and_height), SLE_UINT8);
       
   718 }
       
   719 
       
   720 static void SaveLoad_MAP2() {
       
   721   SlArray(_map2, lengthof(_map2), SLE_UINT8);
       
   722 }
       
   723 
       
   724 static void SaveLoad_M3LO() {
       
   725   SlArray(_map3_lo, lengthof(_map3_lo), SLE_UINT8);
       
   726 }
       
   727 
       
   728 static void SaveLoad_M3HI() {
       
   729   SlArray(_map3_hi, lengthof(_map3_hi), SLE_UINT8);
       
   730 }
       
   731 
       
   732 static void SaveLoad_MAPO() {
       
   733   SlArray(_map_owner, lengthof(_map_owner), SLE_UINT8);
       
   734 }
       
   735 
       
   736 static void SaveLoad_MAP5() {
       
   737   SlArray(_map5, lengthof(_map5), SLE_UINT8);
       
   738 }
       
   739 
       
   740 static void SaveLoad_MAPE() {
       
   741   SlArray(_map_extra_bits, lengthof(_map_extra_bits), SLE_UINT8);
       
   742 }
       
   743 
       
   744 
       
   745 static void Save_CHTS()
       
   746 {
       
   747 	byte count = sizeof(_cheats)/sizeof(Cheat);
       
   748 	Cheat* cht = (Cheat*) &_cheats;
       
   749 	Cheat* cht_last = &cht[count];
       
   750 
       
   751 	SlSetLength(count*2);
       
   752 	for(; cht != cht_last; cht++) {
       
   753 		SlWriteByte(cht->been_used);
       
   754 		SlWriteByte(cht->value);
       
   755 	}
       
   756 }
       
   757 
       
   758 static void Load_CHTS()
       
   759 {
       
   760 	Cheat* cht = (Cheat*) &_cheats;
       
   761 
       
   762 	uint count = SlGetFieldLength()/2;
       
   763 	for(; count; count--, cht++)
       
   764 	{
       
   765 		cht->been_used = (byte)SlReadByte();
       
   766 		cht->value = (byte)SlReadByte();
       
   767 	}
       
   768 }
       
   769 
       
   770 
       
   771 const ChunkHandler _misc_chunk_handlers[] = {
       
   772 	{ 'MAPT', SaveLoad_MAPT, SaveLoad_MAPT, CH_RIFF },
       
   773 	{ 'MAP2', SaveLoad_MAP2, SaveLoad_MAP2, CH_RIFF },
       
   774 	{ 'M3LO', SaveLoad_M3LO, SaveLoad_M3LO, CH_RIFF },
       
   775 	{ 'M3HI', SaveLoad_M3HI, SaveLoad_M3HI, CH_RIFF },
       
   776 	{ 'MAPO', SaveLoad_MAPO, SaveLoad_MAPO, CH_RIFF },
       
   777 	{ 'MAP5', SaveLoad_MAP5, SaveLoad_MAP5, CH_RIFF },
       
   778 	{ 'MAPE', SaveLoad_MAPE, SaveLoad_MAPE, CH_RIFF },
       
   779 
       
   780 	{ 'NAME', Save_NAME, Load_NAME, CH_ARRAY},
       
   781 	{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
       
   782 	{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF},
       
   783 	{ 'OPTS', SaveLoad_OPTS, SaveLoad_OPTS, CH_RIFF},
       
   784 	{ 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST}
       
   785 };