tron@3069: /* $Id$ */ tron@3069: belugas@6889: /** @file road_map.h */ belugas@6889: tron@3145: #ifndef ROAD_MAP_H tron@3145: #define ROAD_MAP_H tron@3069: rubidium@8597: #include "track_func.h" rubidium@8597: #include "rail_type.h" rubidium@8709: #include "town_type.h" rubidium@8598: #include "road_func.h" rubidium@8604: #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) smatz@9025: { rubidium@7866: assert(IsTileType(t, MP_ROAD)); rubidium@7157: return (RoadTileType)GB(_m[t].m5, 6, 2); tron@3150: } tron@3150: frosch@9059: static inline bool IsNormalRoad(TileIndex t) frosch@9059: { frosch@9059: return GetRoadTileType(t) == ROAD_TILE_NORMAL; frosch@9059: } frosch@9059: frosch@9059: static inline bool IsNormalRoadTile(TileIndex t) frosch@9059: { frosch@9059: return IsTileType(t, MP_ROAD) && IsNormalRoad(t); frosch@9059: } frosch@9059: 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@7866: return IsTileType(t, MP_ROAD) && IsLevelCrossing(t); Darkvater@3560: } tron@3150: frosch@9059: static inline bool IsRoadDepot(TileIndex t) frosch@9059: { frosch@9059: return GetRoadTileType(t) == ROAD_TILE_DEPOT; frosch@9059: } frosch@9059: frosch@9059: static inline bool IsRoadDepotTile(TileIndex t) frosch@9059: { frosch@9059: return IsTileType(t, MP_ROAD) && IsRoadDepot(t); frosch@9059: } frosch@9059: rubidium@7157: static inline RoadBits GetRoadBits(TileIndex t, RoadType rt) tron@3272: { frosch@9059: assert(IsNormalRoad(t)); rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4); rubidium@7157: case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4); rubidium@7157: case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4); rubidium@7157: } tron@3369: } tron@3369: skidd13@9230: /** skidd13@9240: * Get all RoadBits set on a tile except from the given RoadType skidd13@9240: * skidd13@9240: * @param t The tile from which we want to get the RoadBits skidd13@9240: * @param rt The RoadType which we exclude from the querry skidd13@9240: * @return all set RoadBits of the tile which are not from the given RoadType skidd13@9240: */ skidd13@9240: static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt) skidd13@9240: { skidd13@9240: return ((rt == ROADTYPE_ROAD) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_ROAD)) | skidd13@9240: ((rt == ROADTYPE_TRAM) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_TRAM)) | skidd13@9240: ((rt == ROADTYPE_HWAY) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_HWAY)); skidd13@9240: } skidd13@9240: skidd13@9240: /** skidd13@9230: * Get all set RoadBits on the given tile skidd13@9230: * skidd13@9230: * @param tile The tile from which we want to get the RoadBits skidd13@9230: * @return all set RoadBits of the tile skidd13@9230: */ rubidium@7157: static inline RoadBits GetAllRoadBits(TileIndex tile) rubidium@7157: { rubidium@7157: return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY); rubidium@7157: } rubidium@7157: rubidium@7157: static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt) tron@3369: { frosch@9059: assert(IsNormalRoad(t)); // XXX incomplete rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break; rubidium@7157: case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break; rubidium@7157: case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break; rubidium@7157: } tron@3369: } tron@3369: rubidium@7157: static inline RoadTypes GetRoadTypes(TileIndex t) rubidium@7157: { rubidium@7866: if (IsTileType(t, MP_ROAD)) { rubidium@7157: return (RoadTypes)GB(_me[t].m7, 5, 3); rubidium@7157: } else { rubidium@7157: return (RoadTypes)GB(_m[t].m3, 0, 3); rubidium@7157: } rubidium@7157: } rubidium@7157: rubidium@7157: static inline void SetRoadTypes(TileIndex t, RoadTypes rt) rubidium@7157: { rubidium@7866: if (IsTileType(t, MP_ROAD)) { rubidium@7157: SB(_me[t].m7, 5, 3, rt); rubidium@7157: } else { rubidium@7157: assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)); rubidium@7157: SB(_m[t].m3, 0, 2, rt); rubidium@7157: } rubidium@7157: } rubidium@7157: frosch@9059: static inline bool HasTileRoadType(TileIndex t, RoadType rt) frosch@9059: { frosch@9059: return HasBit(GetRoadTypes(t), rt); frosch@9059: } frosch@9059: rubidium@7157: static inline Owner GetRoadOwner(TileIndex t, RoadType rt) rubidium@7157: { rubidium@7866: if (!IsTileType(t, MP_ROAD)) return GetTileOwner(t); rubidium@7157: rubidium@7157: switch (GetRoadTileType(t)) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROAD_TILE_NORMAL: rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5); rubidium@7260: case ROADTYPE_TRAM: { rubidium@7260: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@7260: * to OWNER_TOWN makes it use one bit less */ rubidium@7260: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@7260: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@7260: } rubidium@7157: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); rubidium@7157: } rubidium@7157: case ROAD_TILE_CROSSING: rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5); rubidium@7260: case ROADTYPE_TRAM: { rubidium@7260: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@7260: * to OWNER_TOWN makes it use one bit less */ rubidium@7260: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@7260: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@7260: } rubidium@7157: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); rubidium@7157: } rubidium@7157: case ROAD_TILE_DEPOT: return GetTileOwner(t); rubidium@7157: } rubidium@7157: } rubidium@7157: rubidium@7157: static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o) rubidium@7157: { rubidium@7866: if (!IsTileType(t, MP_ROAD)) return SetTileOwner(t, o); rubidium@7157: rubidium@7157: switch (GetRoadTileType(t)) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROAD_TILE_NORMAL: rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break; rubidium@7260: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; rubidium@7157: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; rubidium@7157: } rubidium@7158: break; rubidium@7157: case ROAD_TILE_CROSSING: rubidium@7157: switch (rt) { rubidium@7157: default: NOT_REACHED(); rubidium@7157: case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break; rubidium@7260: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@7260: * to OWNER_TOWN makes it use one bit less */ rubidium@7260: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; rubidium@7157: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; rubidium@7157: } rubidium@7158: break; rubidium@7157: case ROAD_TILE_DEPOT: return SetTileOwner(t, o); rubidium@7157: } rubidium@7157: } tron@3369: rubidium@7260: /** Which directions are disallowed ? */ rubidium@7260: enum DisallowedRoadDirections { rubidium@7260: DRD_NONE, ///< None of the directions are disallowed rubidium@7260: DRD_SOUTHBOUND, ///< All southbound traffic is disallowed rubidium@7260: DRD_NORTHBOUND, ///< All northbound traffic is disallowed rubidium@7260: DRD_BOTH, ///< All directions are disallowed rubidium@7260: DRD_END rubidium@7260: }; rubidium@7260: DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections); rubidium@7260: rubidium@7260: /** rubidium@7260: * Gets the disallowed directions rubidium@7260: * @param t the tile to get the directions from rubidium@7260: * @return the disallowed directions rubidium@7260: */ rubidium@7260: static inline DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t) rubidium@7260: { frosch@9059: assert(IsNormalRoad(t)); rubidium@7260: return (DisallowedRoadDirections)GB(_m[t].m5, 4, 2); rubidium@7260: } rubidium@7260: rubidium@7260: /** rubidium@7260: * Sets the disallowed directions rubidium@7260: * @param t the tile to set the directions for rubidium@7260: * @param drd the disallowed directions rubidium@7260: */ rubidium@7260: static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirections drd) rubidium@7260: { frosch@9059: assert(IsNormalRoad(t)); rubidium@7260: assert(drd < DRD_END); rubidium@7260: SB(_m[t].m5, 4, 2, drd); rubidium@7260: } rubidium@7260: tron@3369: static inline Axis GetCrossingRoadAxis(TileIndex t) tron@3369: { frosch@9059: assert(IsLevelCrossing(t)); rubidium@7157: return (Axis)GB(_m[t].m4, 6, 1); tron@3272: } tron@3272: smatz@9094: static inline Axis GetCrossingRailAxis(TileIndex t) smatz@9094: { smatz@9094: assert(IsLevelCrossing(t)); smatz@9094: return OtherAxis((Axis)GetCrossingRoadAxis(t)); smatz@9094: } smatz@9094: 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: smatz@9094: static inline Track GetCrossingRailTrack(TileIndex tile) smatz@9094: { smatz@9094: return AxisToTrack(GetCrossingRailAxis(tile)); smatz@9094: } smatz@9094: tron@3103: static inline TrackBits GetCrossingRailBits(TileIndex tile) tron@3103: { smatz@9094: return AxisToTrackBits(GetCrossingRailAxis(tile)); tron@3103: } tron@3103: smatz@8840: static inline bool IsCrossingBarred(TileIndex t) smatz@8840: { frosch@9059: assert(IsLevelCrossing(t)); smatz@8840: return HasBit(_m[t].m4, 5); smatz@8840: } smatz@8840: smatz@8840: static inline void SetCrossingBarred(TileIndex t, bool barred) smatz@8840: { frosch@9059: assert(IsLevelCrossing(t)); smatz@8840: SB(_m[t].m4, 5, 1, barred); smatz@8840: } tron@3103: celestar@3322: static inline void UnbarCrossing(TileIndex t) celestar@3322: { smatz@8840: SetCrossingBarred(t, false); celestar@3322: } celestar@3322: celestar@3322: static inline void BarCrossing(TileIndex t) celestar@3322: { smatz@8840: SetCrossingBarred(t, true); celestar@3322: } tron@3274: celestar@3430: #define IsOnDesert IsOnSnow celestar@3430: static inline bool IsOnSnow(TileIndex t) celestar@3430: { skidd13@8424: 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: { skidd13@8428: 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: { frosch@9059: 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 belugas@6886: * 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@9212: * rubidium@9212: * If straight_tunnel_bridge_entrance is set a ROAD_X or ROAD_Y rubidium@9212: * for bridge ramps and tunnel entrances is returned depending rubidium@9212: * on the orientation of the tunnel or bridge. rubidium@6914: * @param tile the tile to get the road bits for rubidium@7157: * @param rt the road type to get the road bits form rubidium@9212: * @param stbe whether to return straight road bits for tunnels/bridges. rubidium@6914: * @return the road bits of the given tile tron@3146: */ rubidium@9212: RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge_entrance = false); tron@3146: rubidium@6914: /** rubidium@6914: * Get the accessible track bits for the given tile. rubidium@6914: * Special behaviour: rubidium@6914: * - road depots: no track bits rubidium@6914: * - non-drive-through stations: no track bits rubidium@6914: * @param tile the tile to get the track bits for rubidium@6914: * @return the track bits for the given tile rubidium@6914: */ rubidium@7157: TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt); tron@3150: rubidium@8598: /** rubidium@8598: * Return if the tile is a valid tile for a crossing. rubidium@8598: * rubidium@8598: * @note function is overloaded rubidium@8598: * @param tile the curent tile rubidium@8598: * @param ax the axis of the road over the rail rubidium@8598: * @return true if it is a valid tile rubidium@8598: */ rubidium@8598: bool IsPossibleCrossing(const TileIndex tile, Axis ax); rubidium@8598: tron@3150: rubidium@7157: static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway) tron@3099: { rubidium@7866: SetTileType(t, MP_ROAD); rubidium@7157: SetTileOwner(t, road); tron@3099: _m[t].m2 = town; rubidium@7157: _m[t].m3 = 0; skidd13@8424: _m[t].m4 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0) << 4 | (HasBit(rot, ROADTYPE_ROAD) ? bits : 0); rubidium@7274: _m[t].m5 = ROAD_TILE_NORMAL << 6; rubidium@7274: SetRoadOwner(t, ROADTYPE_TRAM, tram); skidd13@8424: SB(_m[t].m6, 2, 4, HasBit(rot, ROADTYPE_HWAY) ? bits : 0); rubidium@7157: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: rubidium@7157: 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@7866: SetTileType(t, MP_ROAD); tron@3099: SetTileOwner(t, rail); tron@3099: _m[t].m2 = town; rubidium@7157: _m[t].m3 = rat; rubidium@7157: _m[t].m4 = roaddir << 6 | road; rubidium@7274: _m[t].m5 = ROAD_TILE_CROSSING << 6; rubidium@7274: SetRoadOwner(t, ROADTYPE_TRAM, tram); rubidium@7157: SB(_m[t].m6, 2, 4, 0); rubidium@7157: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: rubidium@7157: static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, RoadType rt) tron@3099: { rubidium@7866: 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; rubidium@7157: _m[t].m5 = ROAD_TILE_DEPOT << 6 | dir; rubidium@7157: SB(_m[t].m6, 2, 4, 0); rubidium@7157: _me[t].m7 = RoadTypeToRoadTypes(rt) << 5; tron@3099: } tron@3099: peter1138@4666: #endif /* ROAD_MAP_H */