1
0
Fork 0

(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.
release/0.4.5
ludde 2005-07-13 19:51:31 +00:00
parent 4b006aa6cf
commit 6013b327f7
15 changed files with 92 additions and 76 deletions

View File

@ -774,7 +774,7 @@ void GenerateClearTile(void)
/* add hills */ /* add hills */
i = ScaleByMapSize((Random() & 0x3FF) + 0x400); i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
do { do {
tile = TILE_MASK(Random()); tile = RandomTile();
if (IsTileType(tile, MP_CLEAR)) if (IsTileType(tile, MP_CLEAR))
_m[tile].m5 = (byte)((_m[tile].m5 & ~(3<<2)) | (1<<2)); _m[tile].m5 = (byte)((_m[tile].m5 & ~(3<<2)) | (1<<2));
} while (--i); } while (--i);
@ -783,7 +783,7 @@ void GenerateClearTile(void)
i = ScaleByMapSize((Random() & 0x7F) + 0x80); i = ScaleByMapSize((Random() & 0x7F) + 0x80);
do { do {
r = Random(); r = Random();
tile = TILE_MASK(r); tile = RandomTileSeed(r);
if (IsTileType(tile, MP_CLEAR)) { if (IsTileType(tile, MP_CLEAR)) {
j = ((r >> 16) & 0xF) + 5; j = ((r >> 16) & 0xF) + 5;
for(;;) { for(;;) {

View File

@ -269,7 +269,7 @@ static void DisasterTick_UFO(Vehicle *v)
return; return;
} }
if (++v->age < 6) { if (++v->age < 6) {
v->dest_tile = TILE_MASK(Random()); v->dest_tile = RandomTile();
return; return;
} }
v->current_order.station = 1; v->current_order.station = 1;
@ -571,12 +571,12 @@ static void DisasterTick_4(Vehicle *v)
} }
if (++v->age < 6) { if (++v->age < 6) {
v->dest_tile = TILE_MASK(Random()); v->dest_tile = RandomTile();
return; return;
} }
v->current_order.station = 1; v->current_order.station = 1;
tile_org = tile = TILE_MASK(Random()); tile_org = tile = RandomTile();
do { do {
if (IsTileType(tile, MP_RAILWAY) && if (IsTileType(tile, MP_RAILWAY) &&
(_m[tile].m5 & ~3) != 0xC0 && IS_HUMAN_PLAYER(GetTileOwner(tile))) (_m[tile].m5 & ~3) != 0xC0 && IS_HUMAN_PLAYER(GetTileOwner(tile)))

View File

@ -101,6 +101,9 @@ void NORETURN CDECL error(const char *str, ...);
#else #else
uint32 Random(void); uint32 Random(void);
uint RandomRange(uint max); uint RandomRange(uint max);
static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
#endif #endif
void InitPlayerRandoms(void); void InitPlayerRandoms(void);

View File

@ -1660,7 +1660,7 @@ static void PlaceInitialIndustry(byte type, int amount)
do { do {
int i = 2000; int i = 2000;
do { do {
if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL) if (CreateNewIndustry(RandomTile(), type) != NULL)
break; break;
} while (--i != 0); } while (--i != 0);
} while (--num); } while (--num);

View File

@ -422,12 +422,11 @@ void RunTileLoop(void)
_cur_tileloop_tile = tile; _cur_tileloop_tile = tile;
} }
void InitializeLandscape(uint log_x, uint log_y) void InitializeLandscape()
{ {
uint map_size; uint map_size;
uint i; uint i;
InitMap(log_x, log_y);
map_size = MapSize(); map_size = MapSize();
for (i = 0; i < map_size; i++) { for (i = 0; i < map_size; i++) {

View File

@ -42,7 +42,7 @@ static int _rename_what;
static byte _terraform_size = 1; static byte _terraform_size = 1;
static byte _last_built_railtype; 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 GenerateIndustries(void);
extern void GenerateTowns(void); extern void GenerateTowns(void);
@ -1080,7 +1080,7 @@ static void ResetLandscape(void)
_random_seeds[0][0] = InteractiveRandom(); _random_seeds[0][0] = InteractiveRandom();
_random_seeds[0][1] = 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(); MarkWholeScreenDirty();
} }

53
map.c
View File

@ -5,28 +5,35 @@
#include "map.h" #include "map.h"
uint _map_log_x; 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; Tile* _m = NULL;
void InitMap(uint log_x, uint log_y) void AllocateMap(uint size_x, uint size_y)
{ {
uint map_size; // Make sure that the map size is within the limits and that
// the x axis size is a power of 2.
if (log_x < 6 || log_x > 11 || log_y < 6 || log_y > 11) 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"); error("Invalid map size");
DEBUG(map, 1)("Allocating map of size %dx%d", log_x, log_y); DEBUG(map, 1)("Allocating map of size %dx%d", size_x, size_y);
_map_log_x = log_x; _map_log_x = FindFirstBit(size_x);
_map_log_y = log_y; _map_size_x = size_x;
_map_size_y = size_y;
// XXX - MSVC6 workaround _map_size = size_x * size_y;
map_size = 1 << (log_x + log_y); _map_tile_mask = _map_size - 1;
// free/malloc uses less memory than realloc.
free(_m); free(_m);
_m = malloc(map_size * sizeof(*_m)); _m = malloc(_map_size * sizeof(*_m));
// XXX TODO handle memory shortage more gracefully // XXX TODO handle memory shortage more gracefully
if (_m == NULL) error("Failed to allocate memory for the map"); 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) uint ScaleByMapSize(uint n)
{ {
int shift = (int)MapLogX() - 8 + (int)MapLogY() - 8; // First shift by 12 to prevent integer overflow for large values of n.
// >>12 is safe since the min mapsize is 64x64
if (shift < 0) // Add (1<<4)-1 to round upwards.
return (n + (1 << -shift) - 1) >> -shift; return (n * (MapSize() >> 12) + (1<<4) - 1) >> 4;
else
return n << shift;
} }
// Scale relative to the circumference of the map
uint ScaleByMapSize1D(uint n) uint ScaleByMapSize1D(uint n)
{ {
int shift = ((int)MapLogX() - 8 + (int)MapLogY() - 8) / 2; // Normal circumference for the X+Y is 256+256 = 1<<9
// Note, not actually taking the full circumference into account,
if (shift < 0) // just half of it.
return (n + (1 << -shift) - 1) >> -shift; // (1<<9) - 1 is there to scale upwards.
else return (n * (MapSizeX() + MapSizeY()) + (1<<9) - 1) >> 9;
return n << shift;
} }

34
map.h
View File

@ -3,8 +3,17 @@
#include "stdafx.h" #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 TILE_ASSERT(x) assert(TILE_MASK(x) == (x));
#define RANDOM_TILE(r) TILE_MASK(r)
typedef struct Tile { typedef struct Tile {
byte type_height; byte type_height;
@ -20,17 +29,18 @@ extern Tile* _m;
void InitMap(uint log_x, uint log_y); 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 // 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 MapLogX(void) { return _map_log_x; }
static inline uint MapLogY(void) { extern uint _map_log_y; return _map_log_y; }
/* The size of the map */ /* The size of the map */
static inline uint MapSizeX(void) { return 1 << MapLogX(); } static inline uint MapSizeX(void) { return _map_size_x; }
static inline uint MapSizeY(void) { return 1 << MapLogY(); } static inline uint MapSizeY(void) { return _map_size_y; }
/* The maximum coordinates */ /* The maximum coordinates */
static inline uint MapMaxX(void) { return MapSizeX() - 1; } static inline uint MapMaxX(void) { return _map_size_x - 1; }
static inline uint MapMaxY(void) { return MapSizeY() - 1; } static inline uint MapMaxY(void) { return _map_size_y - 1; }
/* The number of tiles in the map */ /* 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 // Scale a number relative to the map size
uint ScaleByMapSize(uint); // Scale relative to the number of tiles 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) static inline TileIndex TileXY(uint x, uint y)
{ {
return (y << MapLogX()) + x; return (y * MapSizeX()) + x;
} }
static inline TileIndexDiff TileDiffXY(int x, int y) 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) static inline TileIndex TileVirtXY(uint x, uint y)

24
misc.c
View File

@ -174,7 +174,7 @@ void InitializeAirportGui(void);
void InitializeDock(void); void InitializeDock(void);
void InitializeDockGui(void); void InitializeDockGui(void);
void InitializeIndustries(void); void InitializeIndustries(void);
void InitializeLandscape(uint log_x, uint log_y); void InitializeLandscape(void);
void InitializeTowns(void); void InitializeTowns(void);
void InitializeTrees(void); void InitializeTrees(void);
void InitializeSigns(void); void InitializeSigns(void);
@ -197,10 +197,13 @@ void GenerateTrees(void);
void ConvertGroundTilesIntoWaterTiles(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; 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++) for (i = 0; i < lengthof(_autoreplace_array); i++)
_autoreplace_array[i] = i; _autoreplace_array[i] = i;
@ -229,7 +232,7 @@ void InitializeGame(uint log_x, uint log_y)
InitializeOrders(); InitializeOrders();
InitNewsItemStructs(); InitNewsItemStructs();
InitializeLandscape(log_x, log_y); InitializeLandscape();
InitializeClearLand(); InitializeClearLand();
InitializeRail(); InitializeRail();
InitializeRailGui(); InitializeRailGui();
@ -261,7 +264,7 @@ void InitializeGame(uint log_x, uint log_y)
ResetObjectToPlace(); ResetObjectToPlace();
} }
void GenerateWorld(int mode, uint log_x, uint log_y) void GenerateWorld(int mode, uint size_x, uint size_y)
{ {
int i; int i;
@ -269,7 +272,7 @@ void GenerateWorld(int mode, uint log_x, uint log_y)
_current_player = OWNER_NONE; _current_player = OWNER_NONE;
_generating_world = true; _generating_world = true;
InitializeGame(log_x, log_y); InitializeGame(size_x, size_y);
SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0); SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
// Must start economy early because of the costs. // Must start economy early because of the costs.
@ -851,15 +854,8 @@ static void Save_MAPS(void)
static void Load_MAPS(void) static void Load_MAPS(void)
{ {
uint bits_x = 0;
uint bits_y = 0;
SlGlobList(_map_dimensions); SlGlobList(_map_dimensions);
AllocateMap(_map_dim_x, _map_dim_y);
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);
} }

View File

@ -42,7 +42,7 @@
#include <gpmi/packages/paths.h> #include <gpmi/packages/paths.h>
#endif /* GPMI */ #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 CallLandscapeTick(void);
void IncreaseDate(void); void IncreaseDate(void);
void RunOtherPlayersLoop(void); void RunOtherPlayersLoop(void);
@ -484,7 +484,7 @@ static void LoadIntroGame(void)
sprintf(filename, "%sopntitle.dat", _path.second_data_dir); sprintf(filename, "%sopntitle.dat", _path.second_data_dir);
if (SaveOrLoad(filename, SL_LOAD) != SL_OK) if (SaveOrLoad(filename, SL_LOAD) != SL_OK)
#endif #endif
GenerateWorld(1, 6, 6); // if failed loading, make empty world. GenerateWorld(1, 64, 64); // if failed loading, make empty world.
} }
_pause = 0; _pause = 0;
@ -678,7 +678,7 @@ int ttd_main(int argc, char* argv[])
InitPlayerRandoms(); InitPlayerRandoms();
GenerateWorld(1, 6, 6); // Make the viewport initialization happy GenerateWorld(1, 64, 64); // Make the viewport initialization happy
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
if ((network) && (_network_available)) { if ((network) && (_network_available)) {
@ -763,7 +763,7 @@ static void MakeNewGame(void)
SetupColorsAndInitialWindow(); SetupColorsAndInitialWindow();
// Randomize world // 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 // In a dedicated server, the server does not play
if (_network_dedicated) { if (_network_dedicated) {
@ -795,7 +795,7 @@ static void MakeNewEditorWorld(void)
SetupColorsAndInitialWindow(); SetupColorsAndInitialWindow();
// Startup the game system // 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; _local_player = OWNER_NONE;
MarkWholeScreenDirty(); MarkWholeScreenDirty();
@ -977,7 +977,7 @@ void SwitchMode(int new_mode)
break; break;
case SM_GENRANDLAND: /* Generate random land within scenario editor */ 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 // XXX: set date
_local_player = OWNER_NONE; _local_player = OWNER_NONE;
MarkWholeScreenDirty(); MarkWholeScreenDirty();

View File

@ -1183,7 +1183,7 @@ static const SaveLoadFormat *GetSavegameFormat(const char *s)
} }
// actual loader/saver function // 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 bool AfterLoadGame(uint version);
extern void BeforeSaveGame(void); extern void BeforeSaveGame(void);
extern bool LoadOldSaveGame(const char *file); extern bool LoadOldSaveGame(const char *file);
@ -1307,7 +1307,7 @@ int SaveOrLoad(const char *filename, int mode)
/* Load a TTDLX or TTDPatch game */ /* Load a TTDLX or TTDPatch game */
if (mode == SL_OLD_LOAD) { 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; if (!LoadOldSaveGame(filename)) return SL_REINIT;
AfterLoadGame(0); AfterLoadGame(0);
return SL_OK; 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 /* Old maps were hardcoded to 256x256 and thus did not contain
* any mapsize information. Pre-initialize to 256x256 to not to * any mapsize information. Pre-initialize to 256x256 to not to
* confuse old games */ * confuse old games */
InitializeGame(8, 8); InitializeGame(256, 256);
SlLoadChunks(); SlLoadChunks();
fmt->uninit_read(); fmt->uninit_read();

View File

@ -8,6 +8,8 @@
#pragma warning(disable: 4100) // parameter not used #pragma warning(disable: 4100) // parameter not used
#pragma warning(disable: 4244) // conversion #pragma warning(disable: 4244) // conversion
#pragma warning(disable: 4245) // 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: 4201) // nameless union
#pragma warning(disable: 4514) // removed unref inline #pragma warning(disable: 4514) // removed unref inline
#pragma warning(disable: 4127) // constant conditional expression #pragma warning(disable: 4127) // constant conditional expression

View File

@ -1072,7 +1072,7 @@ Town *CreateRandomTown(uint attempts)
do { do {
// Generate a tile index not too close from the edge // Generate a tile index not too close from the edge
tile = TILE_MASK(Random()); tile = RandomTile();
if (DistanceFromEdge(tile) < 20) if (DistanceFromEdge(tile) < 20)
continue; continue;

View File

@ -96,7 +96,7 @@ static void PlaceMoreTrees(void)
{ {
int i = ScaleByMapSize((Random() & 0x1F) + 25); int i = ScaleByMapSize((Random() & 0x1F) + 25);
do { do {
DoPlaceMoreTrees(TILE_MASK(Random())); DoPlaceMoreTrees(RandomTile());
} while (--i); } while (--i);
} }
@ -109,7 +109,7 @@ void PlaceTreesRandomly(void)
i = ScaleByMapSize(1000); i = ScaleByMapSize(1000);
do { do {
r = Random(); r = Random();
tile = TILE_MASK(r); tile = RandomTileSeed(r);
/* Only on clear tiles, and NOT on farm-tiles or rocks */ /* 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) { if (IsTileType(tile, MP_CLEAR) && (_m[tile].m5 & 0x1F) != 0x0F && (_m[tile].m5 & 0x1C) != 8) {
PlaceTree(tile, r, 0); PlaceTree(tile, r, 0);
@ -122,7 +122,7 @@ void PlaceTreesRandomly(void)
do { do {
r = Random(); r = Random();
tile = TILE_MASK(r); tile = RandomTileSeed(r);
if (IsTileType(tile, MP_CLEAR) && GetMapExtraBits(tile) == 2) { if (IsTileType(tile, MP_CLEAR) && GetMapExtraBits(tile) == 2) {
PlaceTree(tile, r, 0); PlaceTree(tile, r, 0);
} }
@ -602,7 +602,7 @@ void OnTick_Trees(void)
/* place a tree at a random rainforest spot */ /* place a tree at a random rainforest spot */
if (_opt.landscape == LT_DESERT && 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) && IsTileType(tile, MP_CLEAR) &&
(m=_m[tile].m5&0x1C, m<=4) && (m=_m[tile].m5&0x1C, m<=4) &&
(tree=GetRandomTreeType(tile, r>>24)) >= 0) { (tree=GetRandomTreeType(tile, r>>24)) >= 0) {

View File

@ -347,10 +347,7 @@ void GenerateUnmovables(void)
i = ScaleByMapSize(1000); i = ScaleByMapSize(1000);
j = ScaleByMapSize(40); // maximum number of radio towers on the map j = ScaleByMapSize(40); // maximum number of radio towers on the map
do { do {
r = Random(); tile = RandomTile();
tile = r % MapSize();
// TILE_MASK seems to be not working correctly. Radio masts accumulate in one area.
// tile = TILE_MASK(r);
if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h >= 32) { if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h >= 32) {
if(!checkRadioTowerNearby(tile)) if(!checkRadioTowerNearby(tile))
continue; continue;