diff options
author | rubidium <rubidium@openttd.org> | 2007-09-26 16:12:43 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2007-09-26 16:12:43 +0000 |
commit | 01edaeec578bddb73b4513baf9d8bfe5f9a886b0 (patch) | |
tree | 226af8de8514a96ed474dc9590f68e2c517a31d9 | |
parent | a85e18c92200590c84a6c3d3f60dd41f394cc0fe (diff) | |
download | openttd-01edaeec578bddb73b4513baf9d8bfe5f9a886b0.tar.xz |
(svn r11172) -Codechange: rewrite of town road building and addition of the possibility to clean up unconnected road bits during the local road reconstructions. Based on a patch by skidd13.
-rw-r--r-- | projects/openttd.vcproj | 3 | ||||
-rw-r--r-- | projects/openttd_vs80.vcproj | 4 | ||||
-rw-r--r-- | source.list | 1 | ||||
-rw-r--r-- | src/direction.h | 3 | ||||
-rw-r--r-- | src/lang/english.txt | 1 | ||||
-rw-r--r-- | src/map.h | 12 | ||||
-rw-r--r-- | src/road.cpp | 69 | ||||
-rw-r--r-- | src/road.h | 48 | ||||
-rw-r--r-- | src/road_cmd.cpp | 144 | ||||
-rw-r--r-- | src/saveload.cpp | 2 | ||||
-rw-r--r-- | src/settings.cpp | 1 | ||||
-rw-r--r-- | src/settings_gui.cpp | 3 | ||||
-rw-r--r-- | src/town_cmd.cpp | 254 | ||||
-rw-r--r-- | src/variables.h | 2 |
14 files changed, 387 insertions, 160 deletions
diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj index 73e22e264..a821044e0 100644 --- a/projects/openttd.vcproj +++ b/projects/openttd.vcproj @@ -327,6 +327,9 @@ RelativePath=".\..\src\rev.cpp"> </File> <File + RelativePath=".\..\src\road.cpp"> + </File> + <File RelativePath=".\..\src\saveload.cpp"> </File> <File diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 538263ba6..e8559486b 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -668,6 +668,10 @@ > </File> <File + RelativePath=".\..\src\road.cpp" + > + </File> + <File RelativePath=".\..\src\saveload.cpp" > </File> diff --git a/source.list b/source.list index af5cdd4a6..68d5433cd 100644 --- a/source.list +++ b/source.list @@ -58,6 +58,7 @@ players.cpp queue.cpp rail.cpp rev.cpp +road.cpp saveload.cpp screenshot.cpp #if SDL diff --git a/src/direction.h b/src/direction.h index 84d6b952e..9e678c9c9 100644 --- a/src/direction.h +++ b/src/direction.h @@ -165,6 +165,9 @@ enum DiagDirDiff { DIAGDIRDIFF_90LEFT = 3 ///< 90 degrees left }; +/** Allow incrementing of DiagDirDiff variables */ +DECLARE_POSTFIX_INCREMENT(DiagDirDiff); + /** * Applies a difference on a DiagDirection * diff --git a/src/lang/english.txt b/src/lang/english.txt index 22972d9e3..8297e20ef 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1187,6 +1187,7 @@ STR_CONFIG_PATCHES_TOWN_GROWTH_VERY_FAST :Very fast STR_CONFIG_PATCHES_LARGER_TOWNS :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1} STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1} +STR_CONFIG_MODIFIED_ROAD_REBUILD :{LTBLUE}Remove absurd road-elements during the road construction STR_CONFIG_PATCHES_GUI :{BLACK}Interface STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction @@ -390,6 +390,18 @@ static inline TileIndexDiff TileOffsByDir(Direction dir) } /** + * Adds a DiagDir to a tile. + * + * @param tile The current tile + * @param dir The direction in which we want to step + * @return the moved tile + */ +static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir) +{ + return TILE_ADD(tile, TileOffsByDiagDir(dir)); +} + +/** * A callback function type for searching tiles. * * @param tile The tile to test diff --git a/src/road.cpp b/src/road.cpp new file mode 100644 index 000000000..ae806647f --- /dev/null +++ b/src/road.cpp @@ -0,0 +1,69 @@ +#include "stdafx.h" +#include "openttd.h" +#include "functions.h" +#include "rail_map.h" +#include "road.h" +#include "road_map.h" +#include "water_map.h" +#include "macros.h" + +bool IsPossibleCrossing(const TileIndex tile, Axis ax) +{ + return (IsTileType(tile, MP_RAILWAY) && + !HasSignals(tile) && + GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) && + GetTileSlope(tile, NULL) == SLOPE_FLAT); +} + +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) +{ + for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { + const TileIndex neighbor_tile = TileAddByDiagDir(tile, dir); + + /* Get the Roadbit pointing to the neighbor_tile */ + const RoadBits target_rb = DiagDirToRoadBits(dir); + + /* If the roadbit is in the current plan */ + if (org_rb & target_rb) { + bool connective = false; + const RoadBits mirrored_rb = MirrorRoadBits(target_rb); + + switch (GetTileType(neighbor_tile)) { + /* Allways connective ones */ + case MP_CLEAR: case MP_TREES: + connective = true; + break; + + /* The conditionaly connective ones */ + case MP_TUNNELBRIDGE: + case MP_STATION: + case MP_ROAD: { + const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM); + + /* Accept only connective tiles */ + connective = (neighbor_rb & mirrored_rb) || // Neighbor has got the fitting RoadBit + COUNTBITS(neighbor_rb) == 1; // Neighbor has got only one Roadbit + + } break; + + case MP_RAILWAY: + connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir)); + break; + + case MP_WATER: + /* Check for real water tile */ + connective = !IsWater(neighbor_tile); + break; + + /* The defentetly not connective ones */ + default: break; + } + + /* If the neighbor tile is inconnective remove the planed road connection to it */ + if (!connective) org_rb ^= target_rb; + + } + } + + return org_rb; +} diff --git a/src/road.h b/src/road.h index 051508971..e97600f1a 100644 --- a/src/road.h +++ b/src/road.h @@ -116,6 +116,36 @@ static inline RoadBits ComplementRoadBits(RoadBits r) } /** + * Calculate the mirrored RoadBits + * + * Simply move the bits to their new position. + * + * @param r The given RoadBits value + * @return the mirrored + */ +static inline RoadBits MirrorRoadBits(RoadBits r) +{ + return (RoadBits)(GB(r, 0, 2) << 2 | GB(r, 2, 2)); +} + +/** + * Calculate rotated RoadBits + * + * Move the Roadbits clockwise til they are in their final position. + * + * @param r The given RoadBits value + * @param rot The given Rotation angle + * @return the rotated + */ +static inline RoadBits RotateRoadBits(RoadBits r, DiagDirDiff rot) +{ + for (; rot > (DiagDirDiff)0; rot--){ + r = (RoadBits)(GB(r, 0, 1) << 3 | GB(r, 1, 3)); + } + return r; +} + +/** * Create the road-part which belongs to the given DiagDirection * * This function returns a RoadBits value which belongs to @@ -130,6 +160,16 @@ static inline RoadBits DiagDirToRoadBits(DiagDirection d) } /** + * Return if the tile is a valid tile for a crossing. + * + * @note function is overloaded + * @param tile the curent tile + * @param ax the axis of the road over the rail + * @return true if it is a valid tile + */ +bool IsPossibleCrossing(const TileIndex tile, Axis ax); + +/** * Checks whether the trackdir means that we are reversing. * @param dir the trackdir to check * @return true if it is a reversing road trackdir @@ -150,6 +190,14 @@ static inline bool IsStraightRoadTrackdir(Trackdir dir) } /** + * Clean up unneccesary RoadBits of a planed tile. + * @param tile current tile + * @param org_rb planed RoadBits + * @return optimised RoadBits + */ +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb); + +/** * Is it allowed to remove the given road bits from the given tile? * @param tile the tile to remove the road from * @param remove the roadbits that are going to be removed diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 34062376d..f63c20b20 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -259,70 +259,121 @@ CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) static const RoadBits _valid_tileh_slopes_road[][15] = { /* set of normal ones */ { - ROAD_ALL, ROAD_NONE, ROAD_NONE, - ROAD_X, ROAD_NONE, ROAD_NONE, // 3, 4, 5 - ROAD_Y, ROAD_NONE, ROAD_NONE, - ROAD_Y, ROAD_NONE, ROAD_NONE, // 9, 10, 11 - ROAD_X, ROAD_NONE, ROAD_NONE + ROAD_ALL, // SLOPE_FLAT + ROAD_NONE, // SLOPE_W + ROAD_NONE, // SLOPE_S + + ROAD_X, // SLOPE_SW + ROAD_NONE, // SLOPE_E + ROAD_NONE, // SLOPE_EW + + ROAD_Y, // SLOPE_SE + ROAD_NONE, // SLOPE_WSE + ROAD_NONE, // SLOPE_N + + ROAD_Y, // SLOPE_NW + ROAD_NONE, // SLOPE_NS + ROAD_NONE, // SLOPE_NE + + ROAD_X, // SLOPE_ENW + ROAD_NONE, // SLOPE_SEN + ROAD_NONE // SLOPE_ELEVATED }, /* allowed road for an evenly raised platform */ { - ROAD_NONE, - ROAD_SW | ROAD_NW, - ROAD_SW | ROAD_SE, - ROAD_Y | ROAD_SW, - - ROAD_SE | ROAD_NE, // 4 - ROAD_ALL, - ROAD_X | ROAD_SE, - ROAD_ALL, - - ROAD_NW | ROAD_NE, // 8 - ROAD_X | ROAD_NW, - ROAD_ALL, - ROAD_ALL, - - ROAD_Y | ROAD_NE, // 12 - ROAD_ALL, - ROAD_ALL + ROAD_NONE, // SLOPE_FLAT + ROAD_SW | ROAD_NW, // SLOPE_W + ROAD_SW | ROAD_SE, // SLOPE_S + + ROAD_Y | ROAD_SW, // SLOPE_SW + ROAD_SE | ROAD_NE, // SLOPE_E + ROAD_ALL, // SLOPE_EW + + ROAD_X | ROAD_SE, // SLOPE_SE + ROAD_ALL, // SLOPE_WSE + ROAD_NW | ROAD_NE, // SLOPE_N + + ROAD_X | ROAD_NW, // SLOPE_NW + ROAD_ALL, // SLOPE_NS + ROAD_ALL, // SLOPE_NE + + ROAD_Y | ROAD_NE, // SLOPE_ENW + ROAD_ALL, // SLOPE_SEN + ROAD_ALL // SLOPE_ELEVATED }, -}; + /* Singe bits on slopes */ + { + ROAD_ALL, // SLOPE_FLAT + ROAD_NE | ROAD_SE, // SLOPE_W + ROAD_NE | ROAD_NW, // SLOPE_S + + ROAD_NE, // SLOPE_SW + ROAD_NW | ROAD_SW, // SLOPE_E + ROAD_ALL, // SLOPE_EW + ROAD_NW, // SLOPE_SE + ROAD_ALL, // SLOPE_WSE + ROAD_SE | ROAD_SW, // SLOPE_N + ROAD_SE, // SLOPE_NW + ROAD_ALL, // SLOPE_NS + ROAD_ALL, // SLOPE_NE + + ROAD_SW, // SLOPE_ENW + ROAD_ALL, // SLOPE_SEN + ROAD_ALL, // SLOPE_ELEVATED + }, +}; + +/** + * Calculate the costs for roads on slopes + * Aside modify the RoadBits to fit on the slopes + * + * @note The RoadBits are modified too! + * @param tileh The current slope + * @param pieces The RoadBits we want to add + * @param existing The existent RoadBits + * @return The costs for these RoadBits on this slope + */ static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing) { - RoadBits road_bits; - if (IsSteepSlope(tileh)) { - /* force full pieces. */ - *pieces |= (RoadBits)((*pieces & 0xC) >> 2); - *pieces |= (RoadBits)((*pieces & 0x3) << 2); + /* Force straight roads. */ + *pieces |= MirrorRoadBits(*pieces); - if (existing == 0 || existing == *pieces) { + if (existing == ROAD_NONE || existing == *pieces) { if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform; } return CMD_ERROR; } - road_bits = *pieces | existing; + + RoadBits road_bits = *pieces | existing; + + /* Single bits on slopes. + * We check for the roads that need at least 2 bits */ + if (_patches.build_on_slopes && !_is_old_ai_player && + existing == ROAD_NONE && COUNTBITS(*pieces) == 1 && + (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { + return CommandCost(_price.terraform); + } /* no special foundation */ - if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) { + if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == ROAD_NONE) { /* force that all bits are set when we have slopes */ if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh]; return CommandCost(); // no extra cost } /* foundation is used. Whole tile is leveled up */ - if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) { - return CommandCost(existing != 0 ? 0 : _price.terraform); + if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) { + return CommandCost(existing != ROAD_NONE ? 0 : _price.terraform); } - *pieces |= (RoadBits)((*pieces & 0xC) >> 2); - *pieces |= (RoadBits)((*pieces & 0x3) << 2); + /* Force straight roads. */ + *pieces |= MirrorRoadBits(*pieces); /* partly leveled up tile, only if there's no road on that tile */ - if ((existing == 0 || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { - /* force full pieces. */ + if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform; } return CMD_ERROR; @@ -1182,8 +1233,8 @@ static void TileLoop_Road(TileIndex tile) if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) return; + const Town* t = ClosestTownFromTile(tile, (uint)-1); if (!HasRoadWorks(tile)) { - const Town* t = ClosestTownFromTile(tile, (uint)-1); int grp = 0; if (t != NULL) { @@ -1192,8 +1243,8 @@ static void TileLoop_Road(TileIndex tile) /* Show an animation to indicate road work */ if (t->road_build_months != 0 && (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && - GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) { - if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) { + GetRoadTileType(tile) == ROAD_TILE_NORMAL && COUNTBITS(GetAllRoadBits(tile)) > 1 ) { + if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { StartRoadWorks(tile); SndPlayTileFx(SND_21_JACKHAMMER, tile); @@ -1231,6 +1282,17 @@ static void TileLoop_Road(TileIndex tile) } } else if (IncreaseRoadWorksCounter(tile)) { TerminateRoadWorks(tile); + + if (_patches.mod_road_rebuild) { + /* Generate a nicer town surface */ + const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); + const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); + + if (old_rb != new_rb) { + DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD); + } + } + MarkTileDirtyByTile(tile); } } diff --git a/src/saveload.cpp b/src/saveload.cpp index 60e8ae7e2..a02b16a2f 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -29,7 +29,7 @@ #include "strings.h" #include <list> -extern const uint16 SAVEGAME_VERSION = 76; +extern const uint16 SAVEGAME_VERSION = 77; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! diff --git a/src/settings.cpp b/src/settings.cpp index e650cce29..b0e0d00fd 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1438,6 +1438,7 @@ const SettingDesc _patch_settings[] = { SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL), SDT_CONDVAR(Patches, larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL), SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL), + SDT_CONDBOOL(Patches, mod_road_rebuild, 77, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_MODIFIED_ROAD_REBUILD, NULL), /***************************************************************************/ /* AI section of the GUI-configure patches window */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index bb773df0e..d50a1a576 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -672,7 +672,6 @@ static const char *_patches_construction[] = { "drag_signals_density", "oil_refinery_limit", "semaphore_build_before", - "town_layout", }; static const char *_patches_stations[] = { @@ -700,6 +699,8 @@ static const char *_patches_economy[] = { "ending_year", "smooth_economy", "allow_shares", + "town_layout", + "mod_road_rebuild", "town_growth_rate", "larger_towns", "initial_city_size", diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 7649f925a..c89401e11 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -133,18 +133,6 @@ static inline DiagDirection RandomDiagDir() } /** - * 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 @@ -661,7 +649,7 @@ static RoadBits GetTownRoadBits(TileIndex tile) */ static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_multi) { - static TileIndexDiff tid_lt[3]; ///< lookup table for the used diff values + 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)); @@ -681,7 +669,7 @@ static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_mult cur += tid_lt[(pos & 1) ? 0 : 1]; if (pos & 2) cur += tid_lt[2]; - cur = (uint)(pos / 4) * cur; ///< Multiply for the fitting distance + 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; @@ -797,7 +785,7 @@ static void LevelTownLand(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 + TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile RoadBits rcmd = ROAD_NONE; switch (_patches.town_layout) { @@ -849,32 +837,110 @@ static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection di } /** - * Check there are enough neighbor house tiles next to the current tile + * Grows the town with an extra house. + * Check if there are enough neighbor house tiles + * next to the current tile. If there are enough + * add another house. * - * @param tile current tile - * @return true if there are more than 2 house tiles next - * to the current one + * @param t The current town + * @param tile The target tile for the extra house + * @return true if an extra house has been added */ -static bool AreNeighborsHouseTiles(TileIndex tile) +static bool GrowTownWithExtraHouse(Town *t, TileIndex tile) { - uint counter = 0; ///< counts the house neighbor tiles - /* We can't look further than that. */ - if (TileX(tile) < 1 || TileY(tile) < 1) { - return false; + if (TileX(tile) < 2 || TileY(tile) < 2 || MapMaxX() <= TileX(tile) || MapMaxY() <= TileY(tile)) return false; + + uint counter = 0; // counts the house neighbor tiles + + /* Check the tiles E,N,W and S of the current tile for houses */ + for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { + + if (IsTileType(TileAddByDiagDir(tile, dir), MP_HOUSE)) counter++; + + /* If there are enough neighbors stop here */ + if (counter >= 3) { + if (BuildTownHouse(t, tile)) { + _grow_town_result = -1; + return true; + } + return false; + } + } + return false; +} + +/** + * Grows the town with a road piece. + * + * @param t The current town + * @param tile The current tile + * @param rcmd The RoadBits we want to build on the tile + * @return true if the RoadBits have been added else false + */ +static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd) +{ + if (CmdSucceeded(DoCommand(tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) { + _grow_town_result = -1; + return true; + } + return false; +} + +/** + * Grows the town with a bridge. + * At first we check if a bridge is reasonable. + * If so we check if we are able to build it. + * + * @param t The current town + * @param tile The current tile + * @param rcmd The RoadBits which are possible on this tile + * @return true if a bridge has been build else false + */ +static bool GrowTownWithBridge(const Town *t, TileIndex tile, RoadBits rcmd) +{ + 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: 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: return false; } - /* Check the tiles E,N,W and S of the current tile. */ - for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) { - if (IsTileType(AddDiagDirToTileIndex(tile, i), MP_HOUSE)) { - counter++; + /* Check if the bridge will be compatible to the RoadBits */ + if (!(rcmd & DiagDirToRoadBits(ReverseDiagDir(bridge_dir)))) return false; + + /* We are in the right direction */ + uint32 bridge_length = 0; // This value stores the length of the possible bridge + TileIndex bridge_tile = tile; // Used to store the other waterside + + do { + if (bridge_length++ >= 11) { + /* Max 11 tile long bridges */ + return false; } + bridge_tile = TILE_MASK(bridge_tile + TileOffsByDiagDir(bridge_dir)); + } while (IsClearWaterTile(bridge_tile)); - /* If there are enougth neighbor's stop it here */ - if (counter >= 3) { + /* no water tiles in between? */ + if (bridge_length == 1) return false; + + for (uint8 times = 0; times <= 22; times++) { + byte bridge_type = RandomRange(MAX_BRIDGES - 1); + + /* Can we actually build the bridge? */ + if (CmdSucceeded(DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) { + DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE); + _grow_town_result--; return true; } } + /* Quit if it selecting an appropiate bridge type fails a large number of times. */ return false; } @@ -882,25 +948,24 @@ static bool AreNeighborsHouseTiles(TileIndex tile) * Grows the given town. * There are at the moment 3 possible way's for * the town expansion: - * @li Generate a random tile and check if there is a road allowed - * @li TL_ORIGINAL - * @li TL_BETTER_ROADS - * @li Check if the town geometry allows a road and which one - * @li TL_2X2_GRID - * @li TL_3X3_GRID - * @li Forbid roads, only build houses - * @li TL_NO_ROADS + * @li Generate a random tile and check if there is a road allowed + * @li TL_ORIGINAL + * @li TL_BETTER_ROADS + * @li Check if the town geometry allows a road and which one + * @li TL_2X2_GRID + * @li TL_3X3_GRID + * @li Forbid roads, only build houses + * @li TL_NO_ROADS * * @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 cur_rb, DiagDirection target_dir, Town* t1) +static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town *t1) { - 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 + RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command + TileIndex tile = *tile_ptr; // The main tile on which we base our growth TILE_ASSERT(tile); @@ -936,14 +1001,14 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t do target_dir = RandomDiagDir(); while (target_dir == source_dir); } - if (!IsRoadAllowedHere(AddDiagDirToTileIndex(tile, target_dir), target_dir)) { + if (!IsRoadAllowedHere(TileAddByDiagDir(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 (target_dir != ReverseDiagDir(source_dir)) return; /* Return if neither side of the new road is a house */ - if (!IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) && - !IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) { + if (!IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) && + !IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) { return; } @@ -955,7 +1020,7 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t break; } - } else if (target_dir < (DiagDirection)5 && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { + } else if (target_dir < DIAGDIR_END && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { /* Continue building on a partial road. * Should be allways OK, so we only generate * the fitting RoadBits */ @@ -978,8 +1043,7 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t break; } } else { - bool allow_house = false; ///< Value which decides if we want to construct a house - TileIndex tmptile2; ///< Yet another dummy tile + bool allow_house = false; // Value which decides if we want to construct a house /* Reached a tunnel/bridge? Then continue at the other side of it. */ if (IsTileType(tile, MP_TUNNELBRIDGE)) { @@ -997,10 +1061,10 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t if (cur_rb & DiagDirToRoadBits(target_dir)) return; /* This is the tile we will reach if we extend to this direction. */ - tmptile = AddDiagDirToTileIndex(tile, target_dir); + TileIndex house_tile = TileAddByDiagDir(tile, target_dir); // position of a possible house /* Don't walk into water. */ - if (IsClearWaterTile(tmptile)) return; + if (IsClearWaterTile(house_tile)) return; switch (_patches.town_layout) { default: NOT_REACHED(); @@ -1010,41 +1074,35 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t break; case TL_3X3_GRID: /* Use 2x2 grid afterwards! */ - /* Fill gap if house has enougth neighbors */ - tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir); - if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { - _grow_town_result = -1; - } + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ case TL_2X2_GRID: - rcmd = GetTownRoadGridElement(t1, tmptile, target_dir); + rcmd = GetTownRoadGridElement(t1, house_tile, target_dir); allow_house = (rcmd == ROAD_NONE); break; case TL_BETTER_ROADS: /* Use original afterwards! */ - /* Fill gap if house has enougth neighbors */ - tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir); - if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { - _grow_town_result = -1; - } + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ case TL_ORIGINAL: /* Allow a house at the edge. 60% chance or * always ok if no road allowed. */ rcmd = DiagDirToRoadBits(target_dir); - allow_house = (!IsRoadAllowedHere(tmptile, target_dir) || CHANCE16(6, 10)); + allow_house = (!IsRoadAllowedHere(house_tile, 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)) { + if (!IsTileType(house_tile, MP_HOUSE)) { /* Level the land if possible */ - LevelTownLand(tmptile); + LevelTownLand(house_tile); /* And build a house. * Set result to -1 if we managed to build it. */ - if (BuildTownHouse(t1, tmptile)) { + if (BuildTownHouse(t1, house_tile)) { _grow_town_result = -1; } } @@ -1057,51 +1115,13 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t /* 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: 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: - if (CmdSucceeded(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) { - _grow_town_result = -1; - } - return; - } + /* Make the roads look nicer */ + rcmd = CleanUpRoadBits(tile, rcmd); + if (rcmd == ROAD_NONE) return; - /* Check if the bridge is in the right direction */ - if (!(rcmd & DiagDirToRoadBits(bridge_dir))) goto build_road_and_exit; + if (GrowTownWithBridge(t1, tile, rcmd)) return; - /* 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 (bridge_length++ >= 11) { - /* Max 11 tile long bridges */ - goto build_road_and_exit; - } - tmptile = TILE_MASK(tmptile + TileOffsByDiagDir(bridge_dir)); - } while (IsClearWaterTile(tmptile)); - - /* no water tiles in between? */ - 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; - return; - } - } - /* Quit if it selecting an appropiate bridge type fails a large number of times. */ + GrowTownWithRoad(t1, tile, rcmd); } /** Returns "growth" if a house was built, or no if the build failed. @@ -1114,7 +1134,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile) /* Special case. * @see GrowTownInTile Check the else if */ - DiagDirection target_dir = (DiagDirection)5; ///< The direction in which we want to extend the town + DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town TILE_ASSERT(tile); @@ -1137,7 +1157,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile) } do { - RoadBits cur_rb = GetTownRoadBits(tile); ///< The RoadBits of the current tile + RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile /* Try to grow the town from this point */ GrowTownInTile(&tile, cur_rb, target_dir, t); @@ -1151,7 +1171,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile) /* Select a random bit from the blockmask, walk a step * and continue the search from there. */ do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir))); - tile = AddDiagDirToTileIndex(tile, target_dir); + tile = TileAddByDiagDir(tile, target_dir); if (IsTileType(tile, MP_ROAD)) { /* Don't allow building over roads of other cities */ @@ -1220,7 +1240,7 @@ static bool GrowTown(Town *t) PlayerID old_player = _current_player; _current_player = OWNER_TOWN; - TileIndex tile = t->xy; ///< The tile we are working with ATM + TileIndex tile = t->xy; // The tile we are working with ATM /* Find a road that we can base the construction on. */ for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { @@ -2110,8 +2130,8 @@ static void UpdateTownGrowRate(Town *t) /** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the * number of times towns are processed before a new building is built. */ static const uint16 _grow_count_values[2][6] = { - { 120, 120, 120, 100, 80, 60 }, ///< Fund new buildings has been activated - { 320, 420, 300, 220, 160, 100 } ///< Normal values + { 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated + { 320, 420, 300, 220, 160, 100 } // Normal values }; if (t->fund_buildings_months != 0) { @@ -2252,9 +2272,9 @@ void ChangeTownRating(Town *t, int add, int max) /* penalty for removing town-owned stuff */ static const int _default_rating_settings [3][3] = { /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE */ - { 0, 128, 384}, ///< Permissive - { 48, 192, 480}, ///< Neutral - { 96, 384, 768}, ///< Hostile + { 0, 128, 384}, // Permissive + { 48, 192, 480}, // Neutral + { 96, 384, 768}, // Hostile }; bool CheckforTownRating(uint32 flags, Town *t, byte type) diff --git a/src/variables.h b/src/variables.h index 5fbd6ee26..0b385bb73 100644 --- a/src/variables.h +++ b/src/variables.h @@ -242,6 +242,8 @@ struct Patches { bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days. bool autoslope; ///< Allow terraforming under things. + + bool mod_road_rebuild; ///< Roadworks remove unneccesary RoadBits }; VARDEF Patches _patches; |