(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)
authorbelugas
Wed, 12 Sep 2007 23:56:21 +0000
changeset 7566 a8dd64b03224
parent 7565 a7ce188ec44e
child 7567 ab5661f127f8
(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)
src/road.h
src/town_cmd.cpp
--- a/src/road.h	Wed Sep 12 22:05:53 2007 +0000
+++ b/src/road.h	Wed Sep 12 23:56:21 2007 +0000
@@ -126,7 +126,7 @@
  */
 static inline RoadBits DiagDirToRoadBits(DiagDirection d)
 {
-	return (RoadBits)(1U << (3 ^ d));
+	return (RoadBits)(ROAD_NW << (3 ^ d));
 }
 
 /**
--- a/src/town_cmd.cpp	Wed Sep 12 22:05:53 2007 +0000
+++ b/src/town_cmd.cpp	Wed Sep 12 23:56:21 2007 +0000
@@ -122,6 +122,28 @@
 }
 
 /**
+ * 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 @@
 	/* 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 @@
 	}
 }
 
-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 @@
  * @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 @@
 
 	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 @@
  *
  * @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 @@
 	}
 
 	/* 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 @@
  * @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 @@
 
 			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;
-				}
-
-				/* Randomize new road block numbers */
-				a = block;
-				b = block ^ 2;
+				if (!IsRoadAllowedHere(tile, target_dir)) return;
+
+				DiagDirection source_dir = ReverseDiagDir(target_dir);
+
 				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 @@
 					 *  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 @@
 
 			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 @@
 
 		/* 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]));
-
-		/* Don't do it if it reaches to water. */
+		tmptile = AddDiagDirToTileIndex(tile, target_dir);
+
+		/* Don't walk into water. */
 		if (IsClearWaterTile(tmptile)) return;
 
 		switch (_patches.town_layout) {
@@ -1003,19 +1004,19 @@
 
 			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 @@
 			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 @@
 		}
 
 		_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 @@
 	}
 
 	/* 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;
-	}
-
-	tmptile = tile;
-
-	/* Now it contains the direction of the slope */
-	j = -11; // max 11 tile long bridges
+	if (!(rcmd & DiagDirToRoadBits(bridge_dir))) goto build_road_and_exit;
+
+	/* 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;
-
-	/* Quit if it selecting an appropiate bridge type fails a large number of times. */
-	j = 22;
-	do {
+	if (bridge_length == 1) goto build_road_and_exit;
+
+	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 @@
  */
 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 @@
 	}
 
 	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 @@
 	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 @@
 		{ 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;