(svn r2560) Fix: various minor code changes.
authorludde
Wed, 13 Jul 2005 19:51:31 +0000
changeset 2051 44b6b091beb3
parent 2050 947934d248c5
child 2052 4396fc955a39
(svn r2560) Fix: various minor code changes.
Added RandomTile/RandomTileSeed functions to generate a random tile.
Changed landscape routines so they don't assume that the Y map side is a power of two. (support for this is not complete, though)
Changed some frequently used map macros to not compute the values each time.
Silence some warnings on MSVC.
clear_cmd.c
disaster_cmd.c
functions.h
industry_cmd.c
landscape.c
main_gui.c
map.c
map.h
misc.c
openttd.c
saveload.c
stdafx.h
town_cmd.c
tree_cmd.c
unmovable_cmd.c
--- a/clear_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/clear_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -774,7 +774,7 @@
 	/* add hills */
 	i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
 	do {
-		tile = TILE_MASK(Random());
+		tile = RandomTile();
 		if (IsTileType(tile, MP_CLEAR))
 			_m[tile].m5 = (byte)((_m[tile].m5 & ~(3<<2)) | (1<<2));
 	} while (--i);
@@ -783,7 +783,7 @@
 	i = ScaleByMapSize((Random() & 0x7F) + 0x80);
 	do {
 		r = Random();
-		tile = TILE_MASK(r);
+		tile = RandomTileSeed(r);
 		if (IsTileType(tile, MP_CLEAR)) {
 			j = ((r >> 16) & 0xF) + 5;
 			for(;;) {
--- a/disaster_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/disaster_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -269,7 +269,7 @@
 			return;
 		}
 		if (++v->age < 6) {
-			v->dest_tile = TILE_MASK(Random());
+			v->dest_tile = RandomTile();
 			return;
 		}
 		v->current_order.station = 1;
@@ -571,12 +571,12 @@
 		}
 
 		if (++v->age < 6) {
-			v->dest_tile = TILE_MASK(Random());
+			v->dest_tile = RandomTile();
 			return;
 		}
 		v->current_order.station = 1;
 
-		tile_org = tile = TILE_MASK(Random());
+		tile_org = tile = RandomTile();
 		do {
 			if (IsTileType(tile, MP_RAILWAY) &&
 					(_m[tile].m5 & ~3) != 0xC0 && IS_HUMAN_PLAYER(GetTileOwner(tile)))
--- a/functions.h	Wed Jul 13 18:46:51 2005 +0000
+++ b/functions.h	Wed Jul 13 19:51:31 2005 +0000
@@ -101,6 +101,9 @@
 #else
 	uint32 Random(void);
 	uint RandomRange(uint max);
+
+	static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
+	static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
 #endif
 
 void InitPlayerRandoms(void);
--- a/industry_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/industry_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -1660,7 +1660,7 @@
 		do {
 			int i = 2000;
 			do {
-				if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL)
+				if (CreateNewIndustry(RandomTile(), type) != NULL)
 					break;
 			} while (--i != 0);
 		} while (--num);
--- a/landscape.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/landscape.c	Wed Jul 13 19:51:31 2005 +0000
@@ -422,12 +422,11 @@
 	_cur_tileloop_tile = tile;
 }
 
-void InitializeLandscape(uint log_x, uint log_y)
+void InitializeLandscape()
 {
 	uint map_size;
 	uint i;
 
-	InitMap(log_x, log_y);
 
 	map_size = MapSize();
 	for (i = 0; i < map_size; i++) {
--- a/main_gui.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/main_gui.c	Wed Jul 13 19:51:31 2005 +0000
@@ -42,7 +42,7 @@
 
 static byte _terraform_size = 1;
 static byte _last_built_railtype;
-extern void GenerateWorld(int mode, uint log_x, uint log_y);
+extern void GenerateWorld(int mode, uint size_x, uint size_y);
 
 extern void GenerateIndustries(void);
 extern void GenerateTowns(void);
@@ -1080,7 +1080,7 @@
 	_random_seeds[0][0] = InteractiveRandom();
 	_random_seeds[0][1] = InteractiveRandom();
 
-	GenerateWorld(1, _patches.map_x, _patches.map_y);
+	GenerateWorld(1, 1<<_patches.map_x, 1<<_patches.map_y);
 	MarkWholeScreenDirty();
 }
 
--- a/map.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/map.c	Wed Jul 13 19:51:31 2005 +0000
@@ -5,28 +5,35 @@
 #include "map.h"
 
 uint _map_log_x;
-uint _map_log_y;
+uint _map_size_x;
+uint _map_size_y;
+uint _map_tile_mask;
+uint _map_size;
 
 Tile* _m = NULL;
 
 
-void InitMap(uint log_x, uint log_y)
+void AllocateMap(uint size_x, uint size_y)
 {
-	uint map_size;
-
-	if (log_x < 6 || log_x > 11 || log_y < 6 || log_y > 11)
+	// Make sure that the map size is within the limits and that
+	// the x axis size is a power of 2.
+	if (size_x < 64 || size_x > 2048 ||
+			size_y < 64 || size_y > 2048 ||
+			(size_x&(size_x-1)) != 0 ||
+			(size_y&(size_y-1)) != 0)
 		error("Invalid map size");
 
-	DEBUG(map, 1)("Allocating map of size %dx%d", log_x, log_y);
-
-	_map_log_x = log_x;
-	_map_log_y = log_y;
+	DEBUG(map, 1)("Allocating map of size %dx%d", size_x, size_y);
 
-	// XXX - MSVC6 workaround
-	map_size = 1 << (log_x + log_y);
+	_map_log_x = FindFirstBit(size_x);
+	_map_size_x = size_x;
+	_map_size_y = size_y;
+	_map_size = size_x * size_y;
+	_map_tile_mask = _map_size - 1;
 
+	// free/malloc uses less memory than realloc.
 	free(_m);
-	_m = malloc(map_size * sizeof(*_m));
+	_m = malloc(_map_size * sizeof(*_m));
 
 	// XXX TODO handle memory shortage more gracefully
 	if (_m == NULL) error("Failed to allocate memory for the map");
@@ -70,23 +77,21 @@
 
 uint ScaleByMapSize(uint n)
 {
-	int shift = (int)MapLogX() - 8 + (int)MapLogY() - 8;
-
-	if (shift < 0)
-		return (n + (1 << -shift) - 1) >> -shift;
-	else
-		return n << shift;
+	// First shift by 12 to prevent integer overflow for large values of n.
+	// >>12 is safe since the min mapsize is 64x64
+	// Add (1<<4)-1 to round upwards.
+	return (n * (MapSize() >> 12) + (1<<4) - 1) >> 4;
 }
 
 
+// Scale relative to the circumference of the map
 uint ScaleByMapSize1D(uint n)
 {
-	int shift = ((int)MapLogX() - 8 + (int)MapLogY() - 8) / 2;
-
-	if (shift < 0)
-		return (n + (1 << -shift) - 1) >> -shift;
-	else
-		return n << shift;
+	// Normal circumference for the X+Y is 256+256 = 1<<9
+	// Note, not actually taking the full circumference into account,
+	// just half of it.
+	// (1<<9) - 1 is there to scale upwards.
+	return (n * (MapSizeX() + MapSizeY()) + (1<<9) - 1) >> 9;
 }
 
 
--- a/map.h	Wed Jul 13 18:46:51 2005 +0000
+++ b/map.h	Wed Jul 13 19:51:31 2005 +0000
@@ -3,8 +3,17 @@
 
 #include "stdafx.h"
 
-#define TILE_MASK(x) ((x) & ((1 << (MapLogX() + MapLogY())) - 1))
+// Putting externs inside inline functions seems to confuse the aliasing
+// checking on MSVC6. Never use those variables directly.
+extern uint _map_log_x;
+extern uint _map_size_x;
+extern uint _map_size_y;
+extern uint _map_tile_mask;
+extern uint _map_size;
+
+#define TILE_MASK(x) ((x) & _map_tile_mask)
 #define TILE_ASSERT(x) assert(TILE_MASK(x) == (x));
+#define RANDOM_TILE(r) TILE_MASK(r)
 
 typedef struct Tile {
 	byte type_height;
@@ -20,17 +29,18 @@
 
 void InitMap(uint log_x, uint log_y);
 
+void AllocateMap(uint size_x, uint size_y);
+
 // binary logarithm of the map size, try to avoid using this one
-static inline uint MapLogX(void)  { extern uint _map_log_x; return _map_log_x; }
-static inline uint MapLogY(void)  { extern uint _map_log_y; return _map_log_y; }
+static inline uint MapLogX(void)  { return _map_log_x; }
 /* The size of the map */
-static inline uint MapSizeX(void) { return 1 << MapLogX(); }
-static inline uint MapSizeY(void) { return 1 << MapLogY(); }
+static inline uint MapSizeX(void) { return _map_size_x; }
+static inline uint MapSizeY(void) { return _map_size_y; }
 /* The maximum coordinates */
-static inline uint MapMaxX(void) { return MapSizeX() - 1; }
-static inline uint MapMaxY(void) { return MapSizeY() - 1; }
+static inline uint MapMaxX(void) { return _map_size_x - 1; }
+static inline uint MapMaxY(void) { return _map_size_y - 1; }
 /* The number of tiles in the map */
-static inline uint MapSize(void) { return MapSizeX() * MapSizeY(); }
+static inline uint MapSize(void) { return _map_size; }
 
 // Scale a number relative to the map size
 uint ScaleByMapSize(uint); // Scale relative to the number of tiles
@@ -41,12 +51,16 @@
 
 static inline TileIndex TileXY(uint x, uint y)
 {
-	return (y << MapLogX()) + x;
+	return (y * MapSizeX()) + x;
 }
 
 static inline TileIndexDiff TileDiffXY(int x, int y)
 {
-	return (y << MapLogX()) + x;
+	// Multiplication gives much better optimization on MSVC than shifting.
+	// 0 << shift isn't optimized to 0 properly.
+	// Typically x and y are constants, and then this doesn't result
+	// in any actual multiplication in the assembly code..
+	return (y * MapSizeX()) + x;
 }
 
 static inline TileIndex TileVirtXY(uint x, uint y)
--- a/misc.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/misc.c	Wed Jul 13 19:51:31 2005 +0000
@@ -174,7 +174,7 @@
 void InitializeDock(void);
 void InitializeDockGui(void);
 void InitializeIndustries(void);
-void InitializeLandscape(uint log_x, uint log_y);
+void InitializeLandscape(void);
 void InitializeTowns(void);
 void InitializeTrees(void);
 void InitializeSigns(void);
@@ -197,10 +197,13 @@
 
 void ConvertGroundTilesIntoWaterTiles(void);
 
-void InitializeGame(uint log_x, uint log_y)
+void InitializeGame(uint size_x, uint size_y)
 {
+	uint i;
+
+	AllocateMap(size_x, size_y);
+
 	// Initialize the autoreplace array. Needs to be cleared between each game
-	uint i;
 	for (i = 0; i < lengthof(_autoreplace_array); i++)
 		_autoreplace_array[i] = i;
 
@@ -229,7 +232,7 @@
 	InitializeOrders();
 
 	InitNewsItemStructs();
-	InitializeLandscape(log_x, log_y);
+	InitializeLandscape();
 	InitializeClearLand();
 	InitializeRail();
 	InitializeRailGui();
@@ -261,7 +264,7 @@
 	ResetObjectToPlace();
 }
 
-void GenerateWorld(int mode, uint log_x, uint log_y)
+void GenerateWorld(int mode, uint size_x, uint size_y)
 {
 	int i;
 
@@ -269,7 +272,7 @@
 	_current_player = OWNER_NONE;
 
 	_generating_world = true;
-	InitializeGame(log_x, log_y);
+	InitializeGame(size_x, size_y);
 	SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
 
 	// Must start economy early because of the costs.
@@ -851,15 +854,8 @@
 
 static void Load_MAPS(void)
 {
-	uint bits_x = 0;
-	uint bits_y = 0;
-
 	SlGlobList(_map_dimensions);
-
-	for (; _map_dim_x > 1; _map_dim_x >>= 1) ++bits_x;
-	for (; _map_dim_y > 1; _map_dim_y >>= 1) ++bits_y;
-
-	InitMap(bits_x, bits_y);
+	AllocateMap(_map_dim_x, _map_dim_y);
 }
 
 
--- a/openttd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/openttd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -42,7 +42,7 @@
 #include <gpmi/packages/paths.h>
 #endif /* GPMI */
 
-void GenerateWorld(int mode, uint log_x, uint log_y);
+void GenerateWorld(int mode, uint size_x, uint size_y);
 void CallLandscapeTick(void);
 void IncreaseDate(void);
 void RunOtherPlayersLoop(void);
@@ -484,7 +484,7 @@
 		sprintf(filename, "%sopntitle.dat",  _path.second_data_dir);
 		if (SaveOrLoad(filename, SL_LOAD) != SL_OK)
 #endif
-			GenerateWorld(1, 6, 6); // if failed loading, make empty world.
+			GenerateWorld(1, 64, 64); // if failed loading, make empty world.
 	}
 
 	_pause = 0;
@@ -678,7 +678,7 @@
 
 	InitPlayerRandoms();
 
-	GenerateWorld(1, 6, 6); // Make the viewport initialization happy
+	GenerateWorld(1, 64, 64); // Make the viewport initialization happy
 
 #ifdef ENABLE_NETWORK
 	if ((network) && (_network_available)) {
@@ -763,7 +763,7 @@
 	SetupColorsAndInitialWindow();
 
 	// Randomize world
-	GenerateWorld(0, _patches.map_x, _patches.map_y);
+	GenerateWorld(0, 1<<_patches.map_x, 1<<_patches.map_y);
 
 	// In a dedicated server, the server does not play
 	if (_network_dedicated) {
@@ -795,7 +795,7 @@
 	SetupColorsAndInitialWindow();
 
 	// Startup the game system
-	GenerateWorld(1, _patches.map_x, _patches.map_y);
+	GenerateWorld(1, 1<<_patches.map_x, 1<<_patches.map_y);
 
 	_local_player = OWNER_NONE;
 	MarkWholeScreenDirty();
@@ -977,7 +977,7 @@
 		break;
 
 	case SM_GENRANDLAND: /* Generate random land within scenario editor */
-		GenerateWorld(2, _patches.map_x, _patches.map_y);
+		GenerateWorld(2, 1<<_patches.map_x, 1<<_patches.map_y);
 		// XXX: set date
 		_local_player = OWNER_NONE;
 		MarkWholeScreenDirty();
--- a/saveload.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/saveload.c	Wed Jul 13 19:51:31 2005 +0000
@@ -1183,7 +1183,7 @@
 }
 
 // actual loader/saver function
-void InitializeGame(uint log_x, uint log_y);
+void InitializeGame(uint size_x, uint size_y);
 extern bool AfterLoadGame(uint version);
 extern void BeforeSaveGame(void);
 extern bool LoadOldSaveGame(const char *file);
@@ -1307,7 +1307,7 @@
 
   /* Load a TTDLX or TTDPatch game */
 	if (mode == SL_OLD_LOAD) {
-		InitializeGame(8, 8); // set a mapsize of 256x256 for TTDPatch games or it might get confused
+		InitializeGame(256, 256); // set a mapsize of 256x256 for TTDPatch games or it might get confused
 		if (!LoadOldSaveGame(filename)) return SL_REINIT;
 		AfterLoadGame(0);
 		return SL_OK;
@@ -1426,7 +1426,7 @@
 		/* Old maps were hardcoded to 256x256 and thus did not contain
 		 * any mapsize information. Pre-initialize to 256x256 to not to
 		 * confuse old games */
-		InitializeGame(8, 8);
+		InitializeGame(256, 256);
 
 		SlLoadChunks();
 		fmt->uninit_read();
--- a/stdafx.h	Wed Jul 13 18:46:51 2005 +0000
+++ b/stdafx.h	Wed Jul 13 19:51:31 2005 +0000
@@ -8,6 +8,8 @@
 #pragma warning(disable: 4100) // parameter not used
 #pragma warning(disable: 4244) // conversion
 #pragma warning(disable: 4245) // conversion
+#pragma warning(disable: 4305) // 'initializing' : truncation from 'const int ' to 'char '
+#pragma warning(disable: 4018) // warning C4018: '==' : signed/unsigned mismatch
 #pragma warning(disable: 4201) // nameless union
 #pragma warning(disable: 4514) // removed unref inline
 #pragma warning(disable: 4127) // constant conditional expression
--- a/town_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/town_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -1072,7 +1072,7 @@
 
 	do {
 		// Generate a tile index not too close from the edge
-		tile = TILE_MASK(Random());
+		tile = RandomTile();
 		if (DistanceFromEdge(tile) < 20)
 			continue;
 
--- a/tree_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/tree_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -96,7 +96,7 @@
 {
 	int i = ScaleByMapSize((Random() & 0x1F) + 25);
 	do {
-		DoPlaceMoreTrees(TILE_MASK(Random()));
+		DoPlaceMoreTrees(RandomTile());
 	} while (--i);
 }
 
@@ -109,7 +109,7 @@
 	i = ScaleByMapSize(1000);
 	do {
 		r = Random();
-		tile = TILE_MASK(r);
+		tile = RandomTileSeed(r);
 		/* Only on clear tiles, and NOT on farm-tiles or rocks */
 		if (IsTileType(tile, MP_CLEAR) && (_m[tile].m5 & 0x1F) != 0x0F && (_m[tile].m5 & 0x1C) != 8) {
 			PlaceTree(tile, r, 0);
@@ -122,7 +122,7 @@
 
 		do {
 			r = Random();
-			tile = TILE_MASK(r);
+			tile = RandomTileSeed(r);
 			if (IsTileType(tile, MP_CLEAR) && GetMapExtraBits(tile) == 2) {
 				PlaceTree(tile, r, 0);
 			}
@@ -602,7 +602,7 @@
 
 	/* place a tree at a random rainforest spot */
 	if (_opt.landscape == LT_DESERT &&
-			(r=Random(),tile=TILE_MASK(r),GetMapExtraBits(tile)==2) &&
+			(r=Random(),tile=RandomTileSeed(r),GetMapExtraBits(tile)==2) &&
 			IsTileType(tile, MP_CLEAR) &&
 			(m=_m[tile].m5&0x1C, m<=4) &&
 			(tree=GetRandomTreeType(tile, r>>24)) >= 0) {
--- a/unmovable_cmd.c	Wed Jul 13 18:46:51 2005 +0000
+++ b/unmovable_cmd.c	Wed Jul 13 19:51:31 2005 +0000
@@ -347,10 +347,7 @@
 	i = ScaleByMapSize(1000);
 	j = ScaleByMapSize(40); // maximum number of radio towers on the map
 	do {
-		r = Random();
-		tile = r % MapSize();
-//		TILE_MASK seems to be not working correctly. Radio masts accumulate in one area.
-//		tile = TILE_MASK(r);
+		tile = RandomTile();
 		if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h >= 32) {
 			if(!checkRadioTowerNearby(tile))
 				continue;