summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbelugas <belugas@openttd.org>2007-09-12 23:56:21 +0000
committerbelugas <belugas@openttd.org>2007-09-12 23:56:21 +0000
commit1e4f8d7a236e3cdc0871fa0e102a5baa660c7060 (patch)
tree70d4a38a296baa2144329534361deb26380971a1
parentf2dc723da5db03840783b5f00103f2346e64128d (diff)
downloadopenttd-1e4f8d7a236e3cdc0871fa0e102a5baa660c7060.tar.xz
(svn r11091) -Codechange: Partial rewrite of the road management code of towns, in order to make it more readable and with improved performance. (FS#1161 by skidd13)
-rw-r--r--src/road.h2
-rw-r--r--src/town_cmd.cpp393
2 files changed, 198 insertions, 197 deletions
diff --git a/src/road.h b/src/road.h
index 3a6ce33ea..051508971 100644
--- a/src/road.h
+++ b/src/road.h
@@ -126,7 +126,7 @@ static inline RoadBits ComplementRoadBits(RoadBits r)
*/
static inline RoadBits DiagDirToRoadBits(DiagDirection d)
{
- return (RoadBits)(1U << (3 ^ d));
+ return (RoadBits)(ROAD_NW << (3 ^ d));
}
/**
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 1fa6fa97a..4cecdaa15 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -122,6 +122,28 @@ uint OriginalTileRandomiser(uint x, uint y)
}
/**
+ * Return a random direction
+ *
+ * @return a random direction
+ */
+static inline DiagDirection RandomDiagDir()
+{
+ return (DiagDirection)(3 & Random());
+}
+
+/**
+ * Move a TileIndex into a diagonal direction.
+ *
+ * @param tile The current tile
+ * @param dir The direction in which we want to step
+ * @return the moved tile
+ */
+static inline TileIndex AddDiagDirToTileIndex(TileIndex tile, DiagDirection dir)
+{
+ return TILE_ADD(tile, TileOffsByDiagDir(dir));
+}
+
+/**
* House Tile drawing handler.
* Part of the tile loop process
* @param ti TileInfo of the tile to draw
@@ -567,29 +589,6 @@ static void ChangeTileOwner_Town(TileIndex tile, PlayerID old_player, PlayerID n
/* not used */
}
-
-static const TileIndexDiffC _roadblock_tileadd[] = {
- { 0, -1},
- { 1, 0},
- { 0, 1},
- {-1, 0},
-
- /* Store the first 3 elements again.
- * Lets us rotate without using &3. */
- { 0, -1},
- { 1, 0},
- { 0, 1}
-};
-
-/**
- * Distance multiplyer
- * Defines the possible distances between 2 road tiles
- */
-enum RoadBlockTitleDistance {
- RB_TILE_DIST1 = 1, ///< 1 tile between
- RB_TILE_DIST2, ///< 2 tiles between
-};
-
static bool GrowTown(Town *t);
static void TownTickHandler(Town *t)
@@ -627,7 +626,15 @@ void OnTick_Town()
}
}
-static RoadBits GetTownRoadMask(TileIndex tile)
+/**
+ * Return the RoadBits of a tile
+ *
+ * @note There are many other functions doing things like that.
+ * @note Needs to be checked for needlessness.
+ * @param tile The tile we want to analyse
+ * @return The roadbits of the given tile
+ */
+static RoadBits GetTownRoadBits(TileIndex tile)
{
TrackBits b = GetAnyRoadTrackBits(tile, ROADTYPE_ROAD);
RoadBits r = ROAD_NONE;
@@ -649,22 +656,48 @@ static RoadBits GetTownRoadMask(TileIndex tile)
* @param dir target direction
* @param dist_multi distance multiplyer
* @return true if one of the neighboring tiles at the
- * given distance is a road tile else
+ * given distance is a road tile else false
*/
-static bool IsNeighborRoadTile(TileIndex tile, int dir, RoadBlockTitleDistance dist_multi)
+static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_multi)
{
- return (HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 1]))), dir ^ 2) ||
- HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 3]))), dir ^ 2) ||
- HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 1]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir) ||
- HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 3]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir));
+ static TileIndexDiff tid_lt[3]; ///< lookup table for the used diff values
+ tid_lt[0] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT));
+ tid_lt[1] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT));
+ tid_lt[2] = TileOffsByDiagDir(ReverseDiagDir(dir));
+
+ /* We add 1 to the distance because we want to get 1 for
+ * the min distance multiplyer and not 0.
+ * Therefore we start at 4. The 4 is used because
+ * there are 4 tiles per distance step to check.
+ */
+ dist_multi = (dist_multi + 1) * 4;
+ for (uint pos = 4; pos < dist_multi; pos++) {
+ TileIndexDiff cur = 0;
+ /* For each even value of pos add the right TileIndexDiff
+ * for each uneven value the left TileIndexDiff
+ * for each with 2nd bit set (2,3,6,7,..) add the reversed TileIndexDiff
+ */
+ cur += tid_lt[(pos & 1) ? 0 : 1];
+ if (pos & 2) cur += tid_lt[2];
+
+ cur = (uint)(pos / 4) * cur; ///< Multiply for the fitting distance
+ if (GetTownRoadBits(TILE_ADD(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true;
+ }
+ return false;
}
-static bool IsRoadAllowedHere(TileIndex tile, int dir)
+/**
+ * Check if a Road is allowed on a given tile
+ *
+ * @param tile The target tile
+ * @param dir The direction in which we want to extend the town
+ * @return true if it is allowed else false
+ */
+static bool IsRoadAllowedHere(TileIndex tile, DiagDirection dir)
{
if (TileX(tile) < 2 || TileY(tile) < 2 || MapMaxX() <= TileX(tile) || MapMaxY() <= TileY(tile)) return false;
- Slope k;
- Slope slope;
+ Slope cur_slope, desired_slope;
/* If this assertion fails, it might be because the world contains
* land at the edges. This is not ok. */
@@ -672,47 +705,44 @@ static bool IsRoadAllowedHere(TileIndex tile, int dir)
for (;;) {
/* Check if there already is a road at this point? */
- if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) == 0) {
+ if (GetTownRoadBits(tile) == ROAD_NONE) {
/* No, try to build one in the direction.
* if that fails clear the land, and if that fails exit.
* This is to make sure that we can build a road here later. */
- if (CmdFailed(DoCommand(tile, (dir & ROAD_NW ? ROAD_X : ROAD_Y), 0, DC_AUTO, CMD_BUILD_ROAD)) &&
+ if (CmdFailed(DoCommand(tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_X : ROAD_Y), 0, DC_AUTO, CMD_BUILD_ROAD)) &&
CmdFailed(DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR)))
return false;
}
- slope = GetTileSlope(tile, NULL);
- if (slope == SLOPE_FLAT) {
+ cur_slope = GetTileSlope(tile, NULL);
+ if (cur_slope == SLOPE_FLAT) {
no_slope:
/* Tile has no slope */
switch (_patches.town_layout) {
default: NOT_REACHED();
case TL_ORIGINAL: /* Disallow the road if any neighboring tile has a road (distance: 1) */
- return !IsNeighborRoadTile(tile, dir, RB_TILE_DIST1);
+ return !IsNeighborRoadTile(tile, dir, 1);
case TL_BETTER_ROADS: /* Disallow the road if any neighboring tile has a road (distance: 1 and 2). */
- return !(IsNeighborRoadTile(tile, dir, RB_TILE_DIST1) ||
- IsNeighborRoadTile(tile, dir, RB_TILE_DIST2));
+ return !IsNeighborRoadTile(tile, dir, 2);
}
}
/* If the tile is not a slope in the right direction, then
* maybe terraform some. */
- k = (dir & ROAD_NW) ? SLOPE_NE : SLOPE_NW;
- if (k != slope && ComplementSlope(k) != slope) {
+ desired_slope = (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? SLOPE_NE : SLOPE_NW;
+ if (desired_slope != cur_slope && ComplementSlope(desired_slope) != cur_slope) {
uint32 r = Random();
if (CHANCE16I(1, 8, r) && !_generating_world) {
CommandCost res;
if (CHANCE16I(1, 16, r)) {
- res = DoCommand(tile, slope, 0, DC_EXEC | DC_AUTO | DC_NO_WATER,
- CMD_TERRAFORM_LAND);
+ res = DoCommand(tile, cur_slope, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
} else {
/* Note: Do not replace " ^ 0xF" with ComplementSlope(). The slope might be steep. */
- res = DoCommand(tile, slope ^ 0xF, 1, DC_EXEC | DC_AUTO | DC_NO_WATER,
- CMD_TERRAFORM_LAND);
+ res = DoCommand(tile, cur_slope ^ 0xF, 1, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
}
if (CmdFailed(res) && CHANCE16I(1, 3, r)) {
/* We can consider building on the slope, though. */
@@ -759,76 +789,60 @@ static void LevelTownLand(TileIndex tile)
*
* @param t current town
* @param tile tile in reference to the town
+ * @param dir The direction to which we are growing ATM
* @return the RoadBit of the current tile regarding
* the selected town layout
*/
-static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile)
+static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection dir)
{
/* align the grid to the downtown */
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); ///< Vector from downtown to the tile
-
- /* lx, ly description:
- * @li lx and ly are true if the tile is a crossing tile.
- * @li lx xor ly are true if the tile is a straight road tile.
- * @li lx and ly are false if the tile is a house tile.
- */
- bool lx, ly;
+ RoadBits rcmd = ROAD_NONE;
switch (_patches.town_layout) {
default: NOT_REACHED();
case TL_2X2_GRID:
- lx = ((grid_pos.x % 3) == 0);
- ly = ((grid_pos.y % 3) == 0);
+ if ((grid_pos.x % 3) == 0) rcmd |= ROAD_Y;
+ if ((grid_pos.y % 3) == 0) rcmd |= ROAD_X;
break;
case TL_3X3_GRID:
- lx = ((grid_pos.x % 4) == 0);
- ly = ((grid_pos.y % 4) == 0);
+ if ((grid_pos.x % 4) == 0) rcmd |= ROAD_Y;
+ if ((grid_pos.y % 4) == 0) rcmd |= ROAD_X;
break;
}
- /* generate the basic grid structure */
- if (!lx && !ly) { ///< It is a house tile
- return ROAD_NONE;
- } else if (lx && !ly) { ///< It is a Y-dir road tile
- return ROAD_Y;
- } else if (!lx && ly) { ///< It is a X-dir road tile
- return ROAD_X;
- } else { ///< It is a crossing tile
- /* Presets for junctions on slopes
- * not nice :( */
- switch (GetTileSlope(tile, NULL)) {
- case SLOPE_W:
- return ROAD_NW | ROAD_SW;
- case SLOPE_S:
- return ROAD_SE | ROAD_SW;
- case SLOPE_SW:
- return ROAD_Y | ROAD_SW;
- case SLOPE_E:
- return ROAD_NE | ROAD_SE;
- case SLOPE_SE:
- return ROAD_X | ROAD_SE;
- case SLOPE_N:
- return ROAD_NW | ROAD_NE;
- case SLOPE_NW:
- return ROAD_X | ROAD_NW;
- case SLOPE_NE:
- return ROAD_Y | ROAD_NE;
- case SLOPE_STEEP_W:
- case SLOPE_STEEP_N:
- return ROAD_X;
- case SLOPE_STEEP_S:
- case SLOPE_STEEP_E:
- return ROAD_Y;
- default:
- return ROAD_ALL;
- }
+ /* Skip slope optimisations */
+ if (rcmd == ROAD_NONE) return rcmd;
+
+ RoadBits rb_template;
+ switch (GetTileSlope(tile, NULL)) {
+ default: rb_template = ROAD_ALL; break;
+ case SLOPE_W: rb_template = ROAD_NW | ROAD_SW; break;
+ case SLOPE_SW: rb_template = ROAD_Y | ROAD_SW; break;
+ case SLOPE_S: rb_template = ROAD_SE | ROAD_SW; break;
+ case SLOPE_SE: rb_template = ROAD_X | ROAD_SE; break;
+ case SLOPE_E: rb_template = ROAD_NE | ROAD_SE; break;
+ case SLOPE_NE: rb_template = ROAD_Y | ROAD_NE; break;
+ case SLOPE_N: rb_template = ROAD_NW | ROAD_NE; break;
+ case SLOPE_NW: rb_template = ROAD_X | ROAD_NW; break;
+ case SLOPE_STEEP_W:
+ case SLOPE_STEEP_S:
+ case SLOPE_STEEP_E:
+ case SLOPE_STEEP_N:
+ rb_template = (dir == DIAGDIR_NE || dir == DIAGDIR_SW) ? ROAD_X : ROAD_Y;
+ break;
}
+
+ /* Check for the right growth dir */
+ if (DiagDirToRoadBits(ReverseDiagDir(dir)) & (rcmd & rb_template)) return rb_template & rcmd;
+
+ return (dir == DIAGDIR_NE || dir == DIAGDIR_SW) ? ROAD_X : ROAD_Y;
}
/**
- * Check there are enougth neighbor house tiles next to the current tile
+ * Check there are enough neighbor house tiles next to the current tile
*
* @param tile current tile
* @return true if there are more than 2 house tiles next
@@ -844,8 +858,8 @@ static bool AreNeighborsHouseTiles(TileIndex tile)
}
/* Check the tiles E,N,W and S of the current tile. */
- for (uint i = 0; i < 4; i++) {
- if (IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i])), MP_HOUSE)) {
+ for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
+ if (IsTileType(AddDiagDirToTileIndex(tile, i), MP_HOUSE)) {
counter++;
}
@@ -870,25 +884,20 @@ static bool AreNeighborsHouseTiles(TileIndex tile)
* @li Forbid roads, only build houses
* @li TL_NO_ROADS
*
- * @param tile_ptr current tile
- * @param mask current tiles RoadBits
- * @param block road block
- * @param t1 current town
+ * @param tile_ptr The current tile
+ * @param cur_rb The current tiles RoadBits
+ * @param target_dir The target road dir
+ * @param t1 The current town
*/
-static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* t1)
+static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town* t1)
{
- RoadBits rcmd;
- TileIndex tmptile;
- DiagDirection i;
- int j;
- TileIndex tile = *tile_ptr;
+ RoadBits rcmd = ROAD_NONE; ///< RoadBits for the road construction command
+ TileIndex tmptile; ///< Dummy tile for various things
+ TileIndex tile = *tile_ptr; ///< The main tile on which we base our growth
TILE_ASSERT(tile);
- if (mask == 0) {
- int a;
- int b;
-
+ if (cur_rb == ROAD_NONE) {
/* Tile has no road. First reset the status counter
* to say that this is the last iteration. */
_grow_town_result = 0;
@@ -905,37 +914,29 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
case TL_3X3_GRID:
case TL_2X2_GRID:
- rcmd = GetTownRoadGridElement(t1, tile);
- if (rcmd == ROAD_NONE) {
- return;
- }
+ rcmd = GetTownRoadGridElement(t1, tile, target_dir);
+ if (rcmd == ROAD_NONE) return;
break;
case TL_BETTER_ROADS:
case TL_ORIGINAL:
- if (!IsRoadAllowedHere(tile, block)) {
- return;
- }
+ if (!IsRoadAllowedHere(tile, target_dir)) return;
+
+ DiagDirection source_dir = ReverseDiagDir(target_dir);
- /* Randomize new road block numbers */
- a = block;
- b = block ^ 2;
if (CHANCE16(1, 4)) {
- do {
- a = GB(Random(), 0, 2);
- } while (a == b);
+ /* Randomize a new target dir */
+ do target_dir = RandomDiagDir(); while (target_dir == source_dir);
}
- if (!IsRoadAllowedHere(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a])), a)) {
+ if (!IsRoadAllowedHere(AddDiagDirToTileIndex(tile, target_dir), target_dir)) {
/* A road is not allowed to continue the randomized road,
- * return if the road we're trying to build is curved. */
- if (a != (b ^ 2)) {
- return;
- }
+ * return if the road we're trying to build is curved. */
+ if (target_dir != ReverseDiagDir(source_dir)) return;
/* Return if neither side of the new road is a house */
- if (!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 1])), MP_HOUSE) &&
- !IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 3])), MP_HOUSE)) {
+ if (!IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) &&
+ !IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) {
return;
}
@@ -943,13 +944,14 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
* at any side of the new road. */
}
- rcmd = (RoadBits)((ROAD_NW << a) + (ROAD_NW << b));
+ rcmd = DiagDirToRoadBits(target_dir) | DiagDirToRoadBits(source_dir);
break;
}
- } else if (block < 5 && !HASBIT(mask, block ^ 2)) {
+ } else if (target_dir < (DiagDirection)5 && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) {
/* Continue building on a partial road.
- * Always OK. */
+ * Should be allways OK, so we only generate
+ * the fitting RoadBits */
_grow_town_result = 0;
switch (_patches.town_layout) {
@@ -960,18 +962,17 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
case TL_3X3_GRID:
case TL_2X2_GRID:
- rcmd = GetTownRoadGridElement(t1, tile);
+ rcmd = GetTownRoadGridElement(t1, tile, target_dir);
break;
case TL_BETTER_ROADS:
case TL_ORIGINAL:
- rcmd = (RoadBits)(ROAD_NW << (block ^ 2));
+ rcmd = DiagDirToRoadBits(ReverseDiagDir(target_dir));
break;
}
} else {
- int i;
- bool allow_house = false;
- TileIndex tmptile2;
+ bool allow_house = false; ///< Value which decides if we want to construct a house
+ TileIndex tmptile2; ///< Yet another dummy tile
/* Reached a tunnel/bridge? Then continue at the other side of it. */
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
@@ -985,13 +986,13 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
/* Possibly extend the road in a direction.
* Randomize a direction and if it has a road, bail out. */
- i = GB(Random(), 0, 2);
- if (HASBIT(mask, i)) return;
+ target_dir = RandomDiagDir();
+ if (cur_rb & DiagDirToRoadBits(target_dir)) return;
/* This is the tile we will reach if we extend to this direction. */
- tmptile = TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i]));
+ tmptile = AddDiagDirToTileIndex(tile, target_dir);
- /* Don't do it if it reaches to water. */
+ /* Don't walk into water. */
if (IsClearWaterTile(tmptile)) return;
switch (_patches.town_layout) {
@@ -1003,19 +1004,19 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
case TL_3X3_GRID: /* Use 2x2 grid afterwards! */
/* Fill gap if house has enougth neighbors */
- tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i]));
+ tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir);
if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
_grow_town_result = -1;
}
case TL_2X2_GRID:
- rcmd = GetTownRoadGridElement(t1, tmptile);
+ rcmd = GetTownRoadGridElement(t1, tmptile, target_dir);
allow_house = (rcmd == ROAD_NONE);
break;
case TL_BETTER_ROADS: /* Use original afterwards! */
/* Fill gap if house has enougth neighbors */
- tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i]));
+ tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir);
if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
_grow_town_result = -1;
}
@@ -1023,11 +1024,11 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
case TL_ORIGINAL:
/* Allow a house at the edge. 60% chance or
* always ok if no road allowed. */
- allow_house = (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6, 10));
+ rcmd = DiagDirToRoadBits(target_dir);
+ allow_house = (!IsRoadAllowedHere(tmptile, target_dir) || CHANCE16(6, 10));
break;
}
-
if (allow_house) {
/* Build a house, but not if there already is a house there. */
if (!IsTileType(tmptile, MP_HOUSE)) {
@@ -1044,19 +1045,19 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town*
}
_grow_town_result = 0;
- rcmd = (RoadBits)(ROAD_NW << i);
}
/* Return if a water tile */
if (IsClearWaterTile(tile)) return;
+ DiagDirection bridge_dir; ///< The direction of a bridge we maybe want to build
/* Determine direction of slope,
* and build a road if not a special slope. */
switch (GetTileSlope(tile, NULL)) {
- case SLOPE_SW: i = DIAGDIR_NE; break;
- case SLOPE_SE: i = DIAGDIR_NW; break;
- case SLOPE_NW: i = DIAGDIR_SE; break;
- case SLOPE_NE: i = DIAGDIR_SW; break;
+ case SLOPE_SW: bridge_dir = DIAGDIR_NE; break;
+ case SLOPE_SE: bridge_dir = DIAGDIR_NW; break;
+ case SLOPE_NW: bridge_dir = DIAGDIR_SE; break;
+ case SLOPE_NE: bridge_dir = DIAGDIR_SW; break;
default:
build_road_and_exit:
@@ -1067,38 +1068,33 @@ build_road_and_exit:
}
/* Check if the bridge is in the right direction */
- if ((rcmd == ROAD_X && (i == DIAGDIR_NW || i == DIAGDIR_SE)) ||
- (rcmd == ROAD_Y && (i == DIAGDIR_NE || i == DIAGDIR_SW))) {
- goto build_road_and_exit;
- }
+ if (!(rcmd & DiagDirToRoadBits(bridge_dir))) goto build_road_and_exit;
- tmptile = tile;
-
- /* Now it contains the direction of the slope */
- j = -11; // max 11 tile long bridges
+ /* We are in the right direction */
+ uint32 bridge_length = 0; ///< This value stores the length of the possible bridge
+ tmptile = tile; ///< Now we use this dummy to store the other waterside
do {
- if (++j == 0)
+ if (bridge_length++ >= 11) {
+ /* Max 11 tile long bridges */
goto build_road_and_exit;
- tmptile = TILE_MASK(tmptile + TileOffsByDiagDir(i));
+ }
+ tmptile = TILE_MASK(tmptile + TileOffsByDiagDir(bridge_dir));
} while (IsClearWaterTile(tmptile));
/* no water tiles in between? */
- if (j == -10)
- goto build_road_and_exit;
+ if (bridge_length == 1) goto build_road_and_exit;
- /* Quit if it selecting an appropiate bridge type fails a large number of times. */
- j = 22;
- do {
+ for (uint times = 0; times <= 22; times++) {
byte bridge_type = RandomRange(MAX_BRIDGES - 1);
+
/* Can we actually build the bridge? */
if (CmdSucceeded(DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) {
DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE);
- _grow_town_result = -1;
-
- /* obviously, if building any bridge would fail, there is no need to try other bridge-types */
+ _grow_town_result = -1;
return;
}
- } while (--j != 0);
+ }
+ /* Quit if it selecting an appropiate bridge type fails a large number of times. */
}
/** Returns "growth" if a house was built, or no if the build failed.
@@ -1108,7 +1104,10 @@ build_road_and_exit:
*/
static int GrowTownAtRoad(Town *t, TileIndex tile)
{
- int block = 5; // special case
+ /* Special case.
+ * @see GrowTownInTile Check the else if
+ */
+ DiagDirection target_dir = (DiagDirection)5; ///< The direction in which we want to extend the town
TILE_ASSERT(tile);
@@ -1131,22 +1130,21 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
}
do {
- /* Get a bitmask of the road blocks on a tile */
- RoadBits mask = GetTownRoadMask(tile);
+ RoadBits cur_rb = GetTownRoadBits(tile); ///< The RoadBits of the current tile
/* Try to grow the town from this point */
- GrowTownInTile(&tile, mask, block, t);
+ GrowTownInTile(&tile, cur_rb, target_dir, t);
/* Exclude the source position from the bitmask
* and return if no more road blocks available */
- ClrBitT(mask, (block ^ 2));
- if (mask == ROAD_NONE)
+ cur_rb &= ~DiagDirToRoadBits(ReverseDiagDir(target_dir));
+ if (cur_rb == ROAD_NONE)
return _grow_town_result;
/* Select a random bit from the blockmask, walk a step
* and continue the search from there. */
- do block = Random() & 3; while (!HASBIT(mask, block));
- tile += ToTileIndexDiff(_roadblock_tileadd[block]);
+ do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir)));
+ tile = AddDiagDirToTileIndex(tile, target_dir);
if (IsTileType(tile, MP_ROAD)) {
/* Don't allow building over roads of other cities */
@@ -1166,25 +1164,33 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
return (_grow_town_result == -2);
}
-/** Generate a random road block
+/**
+ * Generate a random road block.
* The probability of a straight road
- * is somewhat higher than a curved. */
+ * is somewhat higher than a curved.
+ *
+ * @return A RoadBits value with 2 bits set
+ */
static RoadBits GenRandomRoadBits()
{
uint32 r = Random();
uint a = GB(r, 0, 2);
uint b = GB(r, 8, 2);
if (a == b) b ^= 2;
- return (RoadBits)((1 << a) + (1 << b));
+ return (RoadBits)((ROAD_NW << a) + (ROAD_NW << b));
}
/** Grow the town
* @Return true if a house was built, or no if the build failed. */
static bool GrowTown(Town *t)
{
- TileIndex tile;
- const TileIndexDiffC *ptr;
- PlayerID old_player;
+
+ /* Let the town be a ghost town
+ * The player wanted it in such a way. Thus there he has it. ;)
+ * Never reached in editor mode. */
+ if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
+ return false;
+ }
static const TileIndexDiffC _town_coord_mod[] = {
{-1, 0},
@@ -1201,22 +1207,17 @@ static bool GrowTown(Town *t)
{ 2, -2},
{ 0, 0}
};
-
- /* Let the town be a ghost town
- * The player wanted it in such a way. Thus there he has it. ;)
- * Never reached in editor mode. */
- if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
- return false;
- }
+ const TileIndexDiffC *ptr;
/* Current player is a town */
- old_player = _current_player;
+ PlayerID old_player = _current_player;
_current_player = OWNER_TOWN;
+ TileIndex tile = t->xy; ///< The tile we are working with ATM
+
/* Find a road that we can base the construction on. */
- tile = t->xy;
for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
- if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) != 0) {
+ if (GetTownRoadBits(tile) != ROAD_NONE) {
int r = GrowTownAtRoad(t, tile);
_current_player = old_player;
return r != 0;