(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.
pull/155/head
ludde 19 years ago
parent ca9d0f9841
commit 2123deff13

@ -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(;;) {

@ -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)))

@ -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);

@ -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);

@ -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++) {

@ -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();
}

53
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;
}

34
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)

@ -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);
}

@ -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();

@ -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();

@ -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

@ -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;

@ -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) {

@ -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;

Loading…
Cancel
Save