tron@3069: /* $Id$ */ tron@3069: rubidium@10455: /** @file road_map.h Map accessors for roads. */ glx@9574: tron@3145: #ifndef ROAD_MAP_H tron@3145: #define ROAD_MAP_H tron@3069: rubidium@9723: #include "track_func.h" rubidium@9723: #include "rail_type.h" rubidium@9723: #include "town_type.h" rubidium@9723: #include "road_func.h" rubidium@9723: #include "tile_map.h" tron@3069: tron@3146: rubidium@6574: enum RoadTileType { rubidium@3793: ROAD_TILE_NORMAL, rubidium@3793: ROAD_TILE_CROSSING, rubidium@3793: ROAD_TILE_DEPOT rubidium@6574: }; tron@3369: rubidium@3793: static inline RoadTileType GetRoadTileType(TileIndex t) glx@9732: { rubidium@9694: assert(IsTileType(t, MP_ROAD)); glx@9624: return (RoadTileType)GB(_m[t].m5, 6, 2); tron@3150: } tron@3150: glx@9732: static inline bool IsNormalRoad(TileIndex t) glx@9732: { glx@9732: return GetRoadTileType(t) == ROAD_TILE_NORMAL; glx@9732: } glx@9732: glx@9732: static inline bool IsNormalRoadTile(TileIndex t) glx@9732: { glx@9732: return IsTileType(t, MP_ROAD) && IsNormalRoad(t); glx@9732: } glx@9732: tron@3497: static inline bool IsLevelCrossing(TileIndex t) tron@3497: { rubidium@3793: return GetRoadTileType(t) == ROAD_TILE_CROSSING; tron@3497: } tron@3497: Darkvater@3560: static inline bool IsLevelCrossingTile(TileIndex t) Darkvater@3560: { rubidium@9694: return IsTileType(t, MP_ROAD) && IsLevelCrossing(t); Darkvater@3560: } tron@3150: glx@9732: static inline bool IsRoadDepot(TileIndex t) glx@9732: { glx@9732: return GetRoadTileType(t) == ROAD_TILE_DEPOT; glx@9732: } glx@9732: glx@9732: static inline bool IsRoadDepotTile(TileIndex t) glx@9732: { glx@9732: return IsTileType(t, MP_ROAD) && IsRoadDepot(t); glx@9732: } glx@9732: glx@9624: static inline RoadBits GetRoadBits(TileIndex t, RoadType rt) tron@3272: { glx@9732: assert(IsNormalRoad(t)); glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4); glx@9624: case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4); glx@9624: case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4); glx@9624: } tron@3369: } tron@3369: rubidium@9826: /** rubidium@9826: * Get all RoadBits set on a tile except from the given RoadType rubidium@9826: * rubidium@9826: * @param t The tile from which we want to get the RoadBits rubidium@9826: * @param rt The RoadType which we exclude from the querry rubidium@9826: * @return all set RoadBits of the tile which are not from the given RoadType rubidium@9826: */ rubidium@9826: static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt) rubidium@9826: { rubidium@9826: return ((rt == ROADTYPE_ROAD) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_ROAD)) | rubidium@9826: ((rt == ROADTYPE_TRAM) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_TRAM)) | rubidium@9826: ((rt == ROADTYPE_HWAY) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_HWAY)); rubidium@9826: } rubidium@9826: rubidium@9826: /** rubidium@9826: * Get all set RoadBits on the given tile rubidium@9826: * rubidium@9826: * @param tile The tile from which we want to get the RoadBits rubidium@9826: * @return all set RoadBits of the tile rubidium@9826: */ glx@9624: static inline RoadBits GetAllRoadBits(TileIndex tile) glx@9624: { glx@9624: return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY); glx@9624: } glx@9624: glx@9624: static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt) tron@3369: { glx@9732: assert(IsNormalRoad(t)); // XXX incomplete glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break; glx@9624: case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break; glx@9624: case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break; glx@9624: } tron@3369: } tron@3369: glx@9624: static inline RoadTypes GetRoadTypes(TileIndex t) glx@9624: { rubidium@9694: if (IsTileType(t, MP_ROAD)) { glx@9624: return (RoadTypes)GB(_me[t].m7, 5, 3); glx@9624: } else { glx@9624: return (RoadTypes)GB(_m[t].m3, 0, 3); glx@9624: } glx@9624: } glx@9624: glx@9624: static inline void SetRoadTypes(TileIndex t, RoadTypes rt) glx@9624: { rubidium@9694: if (IsTileType(t, MP_ROAD)) { glx@9624: SB(_me[t].m7, 5, 3, rt); glx@9624: } else { glx@9624: assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)); glx@9624: SB(_m[t].m3, 0, 2, rt); glx@9624: } glx@9624: } glx@9624: glx@9732: static inline bool HasTileRoadType(TileIndex t, RoadType rt) glx@9732: { glx@9732: return HasBit(GetRoadTypes(t), rt); glx@9732: } glx@9732: glx@9624: static inline Owner GetRoadOwner(TileIndex t, RoadType rt) glx@9624: { rubidium@9694: if (!IsTileType(t, MP_ROAD)) return GetTileOwner(t); glx@9624: glx@9624: switch (GetRoadTileType(t)) { glx@9624: default: NOT_REACHED(); glx@9624: case ROAD_TILE_NORMAL: glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5); rubidium@9625: case ROADTYPE_TRAM: { rubidium@9625: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@9625: * to OWNER_TOWN makes it use one bit less */ rubidium@9625: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@9625: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@9625: } glx@9624: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); glx@9624: } glx@9624: case ROAD_TILE_CROSSING: glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5); rubidium@9625: case ROADTYPE_TRAM: { rubidium@9625: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@9625: * to OWNER_TOWN makes it use one bit less */ rubidium@9625: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@9625: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@9625: } glx@9624: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); glx@9624: } glx@9624: case ROAD_TILE_DEPOT: return GetTileOwner(t); glx@9624: } glx@9624: } glx@9624: glx@9624: static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o) glx@9624: { rubidium@9694: if (!IsTileType(t, MP_ROAD)) return SetTileOwner(t, o); glx@9624: glx@9624: switch (GetRoadTileType(t)) { glx@9624: default: NOT_REACHED(); glx@9624: case ROAD_TILE_NORMAL: glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break; rubidium@9625: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; glx@9624: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; glx@9624: } glx@9624: break; glx@9624: case ROAD_TILE_CROSSING: glx@9624: switch (rt) { glx@9624: default: NOT_REACHED(); glx@9624: case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break; rubidium@9625: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@9625: * to OWNER_TOWN makes it use one bit less */ rubidium@9625: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; glx@9624: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; glx@9624: } glx@9624: break; glx@9624: case ROAD_TILE_DEPOT: return SetTileOwner(t, o); glx@9624: } glx@9624: } tron@3369: rubidium@10715: static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o) rubidium@10715: { rubidium@10715: assert(HasTileRoadType(t, rt)); rubidium@10715: return (GetRoadOwner(t, rt) == o); rubidium@10715: } rubidium@10715: rubidium@9625: /** Which directions are disallowed ? */ rubidium@9625: enum DisallowedRoadDirections { rubidium@9625: DRD_NONE, ///< None of the directions are disallowed rubidium@9625: DRD_SOUTHBOUND, ///< All southbound traffic is disallowed rubidium@9625: DRD_NORTHBOUND, ///< All northbound traffic is disallowed rubidium@9625: DRD_BOTH, ///< All directions are disallowed rubidium@9625: DRD_END rubidium@9625: }; rubidium@9625: DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections); rubidium@9625: rubidium@9625: /** rubidium@9625: * Gets the disallowed directions rubidium@9625: * @param t the tile to get the directions from rubidium@9625: * @return the disallowed directions rubidium@9625: */ rubidium@9625: static inline DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t) rubidium@9625: { glx@9732: assert(IsNormalRoad(t)); rubidium@9625: return (DisallowedRoadDirections)GB(_m[t].m5, 4, 2); rubidium@9625: } rubidium@9625: rubidium@9625: /** rubidium@9625: * Sets the disallowed directions rubidium@9625: * @param t the tile to set the directions for rubidium@9625: * @param drd the disallowed directions rubidium@9625: */ rubidium@9625: static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirections drd) rubidium@9625: { glx@9732: assert(IsNormalRoad(t)); rubidium@9625: assert(drd < DRD_END); rubidium@9625: SB(_m[t].m5, 4, 2, drd); rubidium@9625: } rubidium@9625: tron@3369: static inline Axis GetCrossingRoadAxis(TileIndex t) tron@3369: { glx@9732: assert(IsLevelCrossing(t)); glx@9624: return (Axis)GB(_m[t].m4, 6, 1); tron@3272: } tron@3272: glx@9732: static inline Axis GetCrossingRailAxis(TileIndex t) glx@9732: { glx@9732: assert(IsLevelCrossing(t)); glx@9732: return OtherAxis((Axis)GetCrossingRoadAxis(t)); glx@9732: } glx@9732: tron@3070: static inline RoadBits GetCrossingRoadBits(TileIndex tile) tron@3070: { tron@3272: return GetCrossingRoadAxis(tile) == AXIS_X ? ROAD_X : ROAD_Y; tron@3070: } tron@3070: glx@9732: static inline Track GetCrossingRailTrack(TileIndex tile) glx@9732: { glx@9732: return AxisToTrack(GetCrossingRailAxis(tile)); glx@9732: } glx@9732: tron@3103: static inline TrackBits GetCrossingRailBits(TileIndex tile) tron@3103: { glx@9732: return AxisToTrackBits(GetCrossingRailAxis(tile)); tron@3103: } tron@3103: rubidium@9724: static inline bool IsCrossingBarred(TileIndex t) rubidium@9724: { glx@9732: assert(IsLevelCrossing(t)); rubidium@9724: return HasBit(_m[t].m4, 5); rubidium@9724: } rubidium@9724: rubidium@9724: static inline void SetCrossingBarred(TileIndex t, bool barred) rubidium@9724: { glx@9732: assert(IsLevelCrossing(t)); rubidium@9724: SB(_m[t].m4, 5, 1, barred); rubidium@9724: } tron@3103: celestar@3322: static inline void UnbarCrossing(TileIndex t) celestar@3322: { rubidium@9724: SetCrossingBarred(t, false); celestar@3322: } celestar@3322: celestar@3322: static inline void BarCrossing(TileIndex t) celestar@3322: { rubidium@9724: SetCrossingBarred(t, true); celestar@3322: } tron@3274: celestar@3430: #define IsOnDesert IsOnSnow celestar@3430: static inline bool IsOnSnow(TileIndex t) celestar@3430: { rubidium@9722: return HasBit(_m[t].m3, 7); celestar@3430: } celestar@3430: celestar@3430: #define ToggleDesert ToggleSnow celestar@3430: static inline void ToggleSnow(TileIndex t) celestar@3430: { rubidium@9722: ToggleBit(_m[t].m3, 7); celestar@3430: } celestar@3430: celestar@3430: rubidium@6574: enum Roadside { tron@4048: ROADSIDE_BARREN = 0, tron@4048: ROADSIDE_GRASS = 1, tron@4048: ROADSIDE_PAVED = 2, tron@4048: ROADSIDE_STREET_LIGHTS = 3, tron@4048: ROADSIDE_TREES = 5, tron@4048: ROADSIDE_GRASS_ROAD_WORKS = 6, tron@4048: ROADSIDE_PAVED_ROAD_WORKS = 7 rubidium@6574: }; celestar@3430: tron@4048: static inline Roadside GetRoadside(TileIndex tile) celestar@3430: { rubidium@6498: return (Roadside)GB(_m[tile].m3, 4, 3); celestar@3430: } celestar@3430: tron@4048: static inline void SetRoadside(TileIndex tile, Roadside s) celestar@3430: { rubidium@6498: SB(_m[tile].m3, 4, 3, s); celestar@3430: } celestar@3430: celestar@3430: static inline bool HasRoadWorks(TileIndex t) celestar@3430: { tron@4048: return GetRoadside(t) >= ROADSIDE_GRASS_ROAD_WORKS; celestar@3430: } celestar@3430: celestar@3430: static inline bool IncreaseRoadWorksCounter(TileIndex t) celestar@3430: { rubidium@6498: AB(_m[t].m3, 0, 4, 1); celestar@3430: rubidium@6498: return GB(_m[t].m3, 0, 4) == 15; celestar@3430: } celestar@3430: celestar@3430: static inline void StartRoadWorks(TileIndex t) celestar@3430: { celestar@3430: assert(!HasRoadWorks(t)); celestar@3430: /* Remove any trees or lamps in case or roadwork */ tron@4048: switch (GetRoadside(t)) { tron@4048: case ROADSIDE_BARREN: tron@4048: case ROADSIDE_GRASS: SetRoadside(t, ROADSIDE_GRASS_ROAD_WORKS); break; tron@4048: default: SetRoadside(t, ROADSIDE_PAVED_ROAD_WORKS); break; tron@4045: } celestar@3430: } celestar@3430: celestar@3430: static inline void TerminateRoadWorks(TileIndex t) celestar@3430: { celestar@3430: assert(HasRoadWorks(t)); tron@4048: SetRoadside(t, (Roadside)(GetRoadside(t) - ROADSIDE_GRASS_ROAD_WORKS + ROADSIDE_GRASS)); celestar@3430: /* Stop the counter */ rubidium@6498: SB(_m[t].m3, 0, 4, 0); celestar@3430: } celestar@3430: tron@3069: tron@3369: static inline DiagDirection GetRoadDepotDirection(TileIndex t) tron@3069: { glx@9732: assert(IsRoadDepot(t)); tron@3369: return (DiagDirection)GB(_m[t].m5, 0, 2); tron@3167: } tron@3167: tron@3167: tron@3146: /** tron@3146: * Returns the RoadBits on an arbitrary tile glx@9574: * Special behaviour: tron@3146: * - road depots: entrance is treated as road piece tron@3146: * - road tunnels: entrance is treated as road piece tron@3196: * - bridge ramps: start of the ramp is treated as road piece tron@3146: * - bridge middle parts: bridge itself is ignored rubidium@9826: * rubidium@9826: * If straight_tunnel_bridge_entrance is set a ROAD_X or ROAD_Y rubidium@9826: * for bridge ramps and tunnel entrances is returned depending rubidium@9826: * on the orientation of the tunnel or bridge. glx@9574: * @param tile the tile to get the road bits for glx@9624: * @param rt the road type to get the road bits form rubidium@9826: * @param stbe whether to return straight road bits for tunnels/bridges. glx@9574: * @return the road bits of the given tile tron@3146: */ rubidium@9826: RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge_entrance = false); tron@3146: glx@9574: /** glx@9574: * Get the accessible track bits for the given tile. glx@9574: * Special behaviour: glx@9574: * - road depots: no track bits glx@9574: * - non-drive-through stations: no track bits glx@9574: * @param tile the tile to get the track bits for glx@9574: * @return the track bits for the given tile glx@9574: */ glx@9624: TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt); tron@3150: rubidium@9723: /** rubidium@9723: * Return if the tile is a valid tile for a crossing. rubidium@9723: * rubidium@9723: * @note function is overloaded rubidium@9723: * @param tile the curent tile rubidium@9723: * @param ax the axis of the road over the rail rubidium@9723: * @return true if it is a valid tile rubidium@9723: */ rubidium@9723: bool IsPossibleCrossing(const TileIndex tile, Axis ax); rubidium@9723: tron@3150: glx@9624: static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway) tron@3099: { rubidium@9694: SetTileType(t, MP_ROAD); glx@9624: SetTileOwner(t, road); tron@3099: _m[t].m2 = town; glx@9624: _m[t].m3 = 0; rubidium@9722: _m[t].m4 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0) << 4 | (HasBit(rot, ROADTYPE_ROAD) ? bits : 0); rubidium@9625: _m[t].m5 = ROAD_TILE_NORMAL << 6; rubidium@9625: SetRoadOwner(t, ROADTYPE_TRAM, tram); rubidium@9722: SB(_m[t].m6, 2, 4, HasBit(rot, ROADTYPE_HWAY) ? bits : 0); glx@9624: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: glx@9624: static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner hway, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town) tron@3099: { rubidium@9694: SetTileType(t, MP_ROAD); tron@3099: SetTileOwner(t, rail); tron@3099: _m[t].m2 = town; glx@9624: _m[t].m3 = rat; glx@9624: _m[t].m4 = roaddir << 6 | road; rubidium@9625: _m[t].m5 = ROAD_TILE_CROSSING << 6; rubidium@9625: SetRoadOwner(t, ROADTYPE_TRAM, tram); glx@9624: SB(_m[t].m6, 2, 4, 0); glx@9624: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: glx@9624: static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, RoadType rt) tron@3099: { rubidium@9694: SetTileType(t, MP_ROAD); tron@3099: SetTileOwner(t, owner); tron@3099: _m[t].m2 = 0; tron@3099: _m[t].m3 = 0; tron@3099: _m[t].m4 = 0; glx@9624: _m[t].m5 = ROAD_TILE_DEPOT << 6 | dir; glx@9624: SB(_m[t].m6, 2, 4, 0); glx@9624: _me[t].m7 = RoadTypeToRoadTypes(rt) << 5; tron@3099: } tron@3099: peter1138@4666: #endif /* ROAD_MAP_H */