mirror of https://github.com/OpenTTD/OpenTTD
(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
parent
4b006aa6cf
commit
6013b327f7
|
@ -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
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);
|
||||
DEBUG(map, 1)("Allocating map of size %dx%d", size_x, size_y);
|
||||
|
||||
_map_log_x = log_x;
|
||||
_map_log_y = log_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
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)
|
||||
|
|
24
misc.c
24
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
12
openttd.c
12
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();
|
||||
|
|
|
@ -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();
|
||||
|
|
2
stdafx.h
2
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
|
||||
|
|
|
@ -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…
Reference in New Issue