summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorludde <ludde@openttd.org>2005-07-13 19:51:31 +0000
committerludde <ludde@openttd.org>2005-07-13 19:51:31 +0000
commit6013b327f7d54f9d5a331b105011c238da97046f (patch)
tree24c82eee7c186426a35f3ee245d8d753a296d7e2
parent4b006aa6cff4b25f6e9421d3693c2ea51e6b5220 (diff)
downloadopenttd-6013b327f7d54f9d5a331b105011c238da97046f.tar.xz
(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.
-rw-r--r--clear_cmd.c4
-rw-r--r--disaster_cmd.c6
-rw-r--r--functions.h3
-rw-r--r--industry_cmd.c2
-rw-r--r--landscape.c3
-rw-r--r--main_gui.c4
-rw-r--r--map.c53
-rw-r--r--map.h34
-rw-r--r--misc.c24
-rw-r--r--openttd.c12
-rw-r--r--saveload.c6
-rw-r--r--stdafx.h2
-rw-r--r--town_cmd.c2
-rw-r--r--tree_cmd.c8
-rw-r--r--unmovable_cmd.c5
15 files changed, 92 insertions, 76 deletions
diff --git a/clear_cmd.c b/clear_cmd.c
index 45c6f72d7..773d05867 100644
--- a/clear_cmd.c
+++ b/clear_cmd.c
@@ -774,7 +774,7 @@ void GenerateClearTile(void)
/* 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 @@ void GenerateClearTile(void)
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(;;) {
diff --git a/disaster_cmd.c b/disaster_cmd.c
index 19609f7dd..90e005df5 100644
--- a/disaster_cmd.c
+++ b/disaster_cmd.c
@@ -269,7 +269,7 @@ static void DisasterTick_UFO(Vehicle *v)
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 @@ static void DisasterTick_4(Vehicle *v)
}
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)))
diff --git a/functions.h b/functions.h
index a34525f28..4960eb338 100644
--- a/functions.h
+++ b/functions.h
@@ -101,6 +101,9 @@ void NORETURN CDECL error(const char *str, ...);
#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);
diff --git a/industry_cmd.c b/industry_cmd.c
index 511f40c54..fab71b42c 100644
--- a/industry_cmd.c
+++ b/industry_cmd.c
@@ -1660,7 +1660,7 @@ static void PlaceInitialIndustry(byte type, int amount)
do {
int i = 2000;
do {
- if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL)
+ if (CreateNewIndustry(RandomTile(), type) != NULL)
break;
} while (--i != 0);
} while (--num);
diff --git a/landscape.c b/landscape.c
index e47a63ba9..31f134e93 100644
--- a/landscape.c
+++ b/landscape.c
@@ -422,12 +422,11 @@ void RunTileLoop(void)
_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++) {
diff --git a/main_gui.c b/main_gui.c
index e2c05df3b..9a62ef065 100644
--- a/main_gui.c
+++ b/main_gui.c
@@ -42,7 +42,7 @@ static int _rename_what;
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 @@ static void ResetLandscape(void)
_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();
}
diff --git a/map.c b/map.c
index 6330c660e..2eeaa8af1 100644
--- a/map.c
+++ b/map.c
@@ -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 @@ TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
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;
}
diff --git a/map.h b/map.h
index 95370c14e..02513ddd0 100644
--- a/map.h
+++ b/map.h
@@ -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 @@ extern Tile* _m;
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 @@ typedef int32 TileIndexDiff;
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)
diff --git a/misc.c b/misc.c
index 9bb3cbb55..9e87baf97 100644
--- a/misc.c
+++ b/misc.c
@@ -174,7 +174,7 @@ void InitializeAirportGui(void);
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 GenerateTrees(void);
void ConvertGroundTilesIntoWaterTiles(void);
-void InitializeGame(uint log_x, uint log_y)
+void InitializeGame(uint size_x, uint size_y)
{
- // Initialize the autoreplace array. Needs to be cleared between each game
uint i;
+
+ AllocateMap(size_x, size_y);
+
+ // Initialize the autoreplace array. Needs to be cleared between each game
for (i = 0; i < lengthof(_autoreplace_array); i++)
_autoreplace_array[i] = i;
@@ -229,7 +232,7 @@ void InitializeGame(uint log_x, uint log_y)
InitializeOrders();
InitNewsItemStructs();
- InitializeLandscape(log_x, log_y);
+ InitializeLandscape();
InitializeClearLand();
InitializeRail();
InitializeRailGui();
@@ -261,7 +264,7 @@ void InitializeGame(uint log_x, uint log_y)
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 @@ void GenerateWorld(int mode, uint log_x, uint log_y)
_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 Save_MAPS(void)
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);
}
diff --git a/openttd.c b/openttd.c
index 0a63fe326..9abf6e78a 100644
--- a/openttd.c
+++ b/openttd.c
@@ -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 @@ static void LoadIntroGame(void)
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 @@ int ttd_main(int argc, char* argv[])
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 @@ static void MakeNewGame(void)
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 @@ static void MakeNewEditorWorld(void)
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 @@ void SwitchMode(int new_mode)
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();
diff --git a/saveload.c b/saveload.c
index b120f0535..d2fc3748f 100644
--- a/saveload.c
+++ b/saveload.c
@@ -1183,7 +1183,7 @@ static const SaveLoadFormat *GetSavegameFormat(const char *s)
}
// 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 @@ int SaveOrLoad(const char *filename, int mode)
/* 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 @@ int SaveOrLoad(const char *filename, int mode)
/* 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();
diff --git a/stdafx.h b/stdafx.h
index c7c1aa83d..414e06ea9 100644
--- a/stdafx.h
+++ b/stdafx.h
@@ -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
diff --git a/town_cmd.c b/town_cmd.c
index 13df9d103..20e29569e 100644
--- a/town_cmd.c
+++ b/town_cmd.c
@@ -1072,7 +1072,7 @@ Town *CreateRandomTown(uint attempts)
do {
// Generate a tile index not too close from the edge
- tile = TILE_MASK(Random());
+ tile = RandomTile();
if (DistanceFromEdge(tile) < 20)
continue;
diff --git a/tree_cmd.c b/tree_cmd.c
index 66939a7d5..179205670 100644
--- a/tree_cmd.c
+++ b/tree_cmd.c
@@ -96,7 +96,7 @@ static void PlaceMoreTrees(void)
{
int i = ScaleByMapSize((Random() & 0x1F) + 25);
do {
- DoPlaceMoreTrees(TILE_MASK(Random()));
+ DoPlaceMoreTrees(RandomTile());
} while (--i);
}
@@ -109,7 +109,7 @@ void PlaceTreesRandomly(void)
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 @@ void PlaceTreesRandomly(void)
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 @@ void OnTick_Trees(void)
/* 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) {
diff --git a/unmovable_cmd.c b/unmovable_cmd.c
index f18ebaa08..e44649bce 100644
--- a/unmovable_cmd.c
+++ b/unmovable_cmd.c
@@ -347,10 +347,7 @@ void GenerateUnmovables(void)
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;