From 9ca761b06534ed191b0624a6c7049db296997a73 Mon Sep 17 00:00:00 2001 From: celestar Date: Sat, 16 Jul 2005 23:47:37 +0000 Subject: [PATCH] (svn r2595) -Codechange: Introduced "IsSteepTileh" to find whether a tile is steep (i.e. spans two height levels) and use it throughout the code. -Codechange: Add CanBuildDepotByTileh to find if a tile is suitable to build a depot on it. Wraps some bitmagic which seems quite unreadable at first glance --- depot.h | 25 +++++++++++++++++++++++++ industry_cmd.c | 2 +- main_gui.c | 4 ++-- rail_cmd.c | 26 ++++++++++++++++++++++---- road_cmd.c | 17 ++++++++++++----- station_cmd.c | 14 ++++++++++++-- tile.h | 5 +++++ tree_cmd.c | 2 +- tunnelbridge_cmd.c | 4 ++-- viewport.c | 2 +- waypoint.c | 5 ++++- 11 files changed, 87 insertions(+), 19 deletions(-) diff --git a/depot.h b/depot.h index f60124a2c7..a08fadb12b 100644 --- a/depot.h +++ b/depot.h @@ -1,6 +1,9 @@ #ifndef DEPOT_H #define DEPOT_H +/** @file depot.h Header files for depots (not hangars) + * @see depot.c */ + #include "pool.h" #include "tile.h" @@ -112,6 +115,28 @@ static inline DiagDirection GetDepotDirection(TileIndex tile, TransportType type } } +/** + Find out if the slope of the tile is suitable to build a depot of given direction + @param direction The direction in which the depot's exit points. Starts with 0 as NE and goes Clockwise + @param tileh The slope of the tile in question + @return true if the construction is possible + + + This is checked by the ugly 0x4C >> direction magic, which does the following: + 0x4C is 0100 1100 and tileh has only bits 0..3 set (steep tiles are ruled out) + So: for direction (only the significant bits are shown)

+ 00 (exit towards NE) we need either bit 2 or 3 set in tileh: 0x4C >> 0 = 1100

+ 01 (exit towards SE) we need either bit 1 or 2 set in tileh: 0x4C >> 1 = 0110

+ 02 (exit towards SW) we need either bit 0 or 1 set in tileh: 0x4C >> 2 = 0011

+ 03 (exit towards NW) we need either bit 0 or 4 set in tileh: 0x4C >> 3 = 1001

+ So ((0x4C >> p2) & tileh) determines whether the depot can be built on the current tileh +*/ +static inline bool CanBuildDepotByTileh(uint32 direction, uint tileh) +{ + return (0x4C >> direction) & tileh; +} + + Depot *GetDepotByTile(TileIndex tile); void InitializeDepot(void); Depot *AllocateDepot(void); diff --git a/industry_cmd.c b/industry_cmd.c index 410d35cf01..066f2d58bc 100644 --- a/industry_cmd.c +++ b/industry_cmd.c @@ -1339,7 +1339,7 @@ static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable } else { if (ti.type == MP_WATER && ti.map5 == 0) return false; - if (ti.tileh & 0x10) + if (IsSteepTileh(ti.tileh)) return false; if (ti.tileh != 0) { diff --git a/main_gui.c b/main_gui.c index 9a62ef0657..337f2a1282 100644 --- a/main_gui.c +++ b/main_gui.c @@ -1218,7 +1218,7 @@ static void PlaceProc_LightHouse(TileIndex tile) TileInfo ti; FindLandscapeHeightByTile(&ti, tile); - if (ti.type != MP_CLEAR || (ti.tileh & 0x10)) + if (IsTileType(tile, MP_CLEAR) || IsSteepTileh(ti.tileh)) return; ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAP5, 1); @@ -1230,7 +1230,7 @@ static void PlaceProc_Transmitter(TileIndex tile) TileInfo ti; FindLandscapeHeightByTile(&ti, tile); - if (ti.type != MP_CLEAR || (ti.tileh & 0x10)) + if (IsTileType(tile, MP_CLEAR) || IsSteepTileh(ti.tileh)) return; ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAP5, 0); diff --git a/rail_cmd.c b/rail_cmd.c index 082d1a6337..825a357e8b 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -217,7 +217,7 @@ uint GetRailFoundation(uint tileh, uint bits) static uint32 CheckRailSlope(uint tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile) { // never allow building on top of steep tiles - if (!(tileh & 0x10)) { + if (!IsSteepTileh(tileh)) { rail_bits |= existing; // don't allow building on the lower side of a coast @@ -634,7 +634,10 @@ int32 CmdRemoveRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2) /** Build a train depot * @param x,y position of the train depot * @param p1 rail type - * @param p2 depot direction (0 through 3), where 0 is NW, 1 is NE, etc. + * @param p2 depot direction (0 through 3), where 0 is NE, 1 is SE, 2 is SW, 3 is NW + * + * @todo When checking for the tile slope, + * distingush between "Flat land required" and "land sloped in wrong direction" */ int32 CmdBuildTrainDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -650,8 +653,23 @@ int32 CmdBuildTrainDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (!ValParamRailtype(p1) || p2 > 3) return CMD_ERROR; tileh = GetTileSlope(tile, NULL); - if (tileh != 0) { - if ((!_patches.ainew_active && _is_ai_player) || !_patches.build_on_slopes || (tileh & 0x10 || !((0x4C >> p2) & tileh) )) + + /* Prohibit construction if + The tile is non-flat AND + 1) The AI is "old-school" + 2) build-on-slopes is disabled + 3) the tile is steep i.e. spans two height levels + 4) the exit points in the wrong direction + + */ + + if (tileh != 0 && ( + (!_patches.ainew_active && _is_ai_player) || + !_patches.build_on_slopes || + IsSteepTileh(tileh) || + !CanBuildDepotByTileh(p2, tileh) + ) + ) { return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); } diff --git a/road_cmd.c b/road_cmd.c index 3996901efc..4fa2626410 100644 --- a/road_cmd.c +++ b/road_cmd.c @@ -322,7 +322,7 @@ static const byte _valid_tileh_slopes_road[3][15] = { static uint32 CheckRoadSlope(int tileh, byte *pieces, byte existing) { - if (!(tileh & 0x10)) { + if (!IsSteepTileh(tileh)) { byte road_bits = *pieces | existing; // no special foundation @@ -385,7 +385,7 @@ int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) } else if (ti.type == MP_RAILWAY) { byte m5; - if (ti.tileh & 0x10) // very steep tile + if (IsSteepTileh(ti.tile)) // very steep tile return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); if(!_valid_tileh_slopes_road[2][ti.tileh]) // prevent certain slopes @@ -417,7 +417,7 @@ int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) } else if (ti.type == MP_TUNNELBRIDGE) { /* check for flat land */ - if (ti.tileh & 0x10) // very steep tile + if (IsSteepTileh(ti.tileh)) // very steep tile return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); /* is this middle part of a bridge? */ @@ -620,6 +620,9 @@ int32 CmdRemoveLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) * @param x,y tile coordinates where the depot will be built * @param p1 depot direction (0 through 3), where 0 is NW, 1 is NE, etc. * @param p2 unused + * + * @todo When checking for the tile slope, + * distingush between "Flat land required" and "land sloped in wrong direction" */ int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -639,8 +642,12 @@ int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (!EnsureNoVehicle(tile)) return CMD_ERROR; - if (ti.tileh != 0) { - if (!_patches.build_on_slopes || (ti.tileh & 0x10 || !((0x4C >> p1) & ti.tileh) )) + if ((ti.tileh != 0) && ( + !_patches.build_on_slopes || + IsSteepTileh(ti.tileh) || + !CanBuildDepotByTileh(p1, ti.tileh) + ) + ) { return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); } diff --git a/station_cmd.c b/station_cmd.c index c39a832e72..3dcd34b2f0 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -764,8 +764,18 @@ int32 CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint invali tileh = GetTileSlope(tile_cur, &z); - // steep slopes are completely prohibited - if (tileh & 0x10 || (((!_patches.ainew_active && _is_ai_player) || !_patches.build_on_slopes) && tileh != 0)) { + /* Prohibit building if + 1) The tile is "steep" (i.e. stretches two height levels) + -OR- + 2) The tile is non-flat if + a) the player building is an "old-school" AI + -OR- + b) the build_on_slopes switch is disabled + */ + if (IsSteepTileh(tileh) || + (((!_patches.ainew_active && _is_ai_player) || !_patches.build_on_slopes) + && tileh != 0)) { + _error_message = STR_0007_FLAT_LAND_REQUIRED; return CMD_ERROR; } diff --git a/tile.h b/tile.h index 2a34e85e44..9074f86013 100644 --- a/tile.h +++ b/tile.h @@ -61,6 +61,11 @@ static inline uint TileHeight(TileIndex tile) return GB(_m[tile].type_height, 0, 4); } +static inline bool IsSteepTileh(uint tileh) +{ + return (tileh & 0x10); +} + static inline void SetTileHeight(TileIndex tile, uint height) { assert(tile < MapSize()); diff --git a/tree_cmd.c b/tree_cmd.c index 1792056700..ce9cd320ce 100644 --- a/tree_cmd.c +++ b/tree_cmd.c @@ -289,7 +289,7 @@ static void DrawTile_Trees(TileInfo *ti) z = ti->z; if (ti->tileh != 0) { z += 4; - if (ti->tileh & 0x10) + if (IsSteepTileh(ti->tileh)) z += 4; } diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index 836e2b20df..d2d4a67e09 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -88,7 +88,7 @@ enum { */ static uint32 CheckBridgeSlope(uint direction, uint tileh, bool is_start_tile) { - if (!(tileh & 0x10)) { // disable building on very steep slopes + if (!IsSteepTileh(tileh)) { // disable building on very steep slopes if (is_start_tile) { /* check slope at start tile @@ -981,7 +981,7 @@ static void DrawBridgePillars(TileInfo *ti, int x, int y, int z) p = _tileh_bits[(image & 1) * 2 + (ti->map5&0x01)]; front_height = ti->z + ((ti->tileh & p[0])?8:0); back_height = ti->z + ((ti->tileh & p[1])?8:0); - if (ti->tileh & 0x10) { + if (IsSteepTileh(ti->tileh)) { if (!(ti->tileh & p[2])) front_height += 8; if (!(ti->tileh & p[3])) back_height += 8; } diff --git a/viewport.c b/viewport.c index 44e8e557ae..3cb0bda0eb 100644 --- a/viewport.c +++ b/viewport.c @@ -669,7 +669,7 @@ static void DrawTileSelection(const TileInfo *ti) byte z = ti->z; if (ti->tileh & 8) { z += 8; - if (!(ti->tileh & 2) && (ti->tileh & 0x10)) { + if (!(ti->tileh & 2) && (IsSteepTileh(ti->tileh))) { z += 8; } } diff --git a/waypoint.c b/waypoint.c index aa5d543b4b..539d72b456 100644 --- a/waypoint.c +++ b/waypoint.c @@ -152,6 +152,9 @@ static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile) * @param x,y coordinates where waypoint will be built * @param p1 graphics for waypoint type, bit 8 signifies custom waypoint gfx (& 0x100) * @param p2 unused + * + * @todo When checking for the tile slope, + * distingush between "Flat land required" and "land sloped in wrong direction" */ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -175,7 +178,7 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2) tileh = GetTileSlope(tile, NULL); if (tileh != 0) { - if (!_patches.build_on_slopes || tileh & 0x10 || !(tileh & (0x3 << dir)) || !(tileh & ~(0x3 << dir))) + if (!_patches.build_on_slopes || IsSteepTileh(tileh) || !(tileh & (0x3 << dir)) || !(tileh & ~(0x3 << dir))) return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); }