tron@3069: /* $Id$ */ tron@3069: belugas@6393: /** @file road_map.h */ belugas@6393: tron@3145: #ifndef ROAD_MAP_H tron@3145: #define ROAD_MAP_H tron@3069: rubidium@8101: #include "track_func.h" rubidium@8101: #include "rail_type.h" rubidium@8213: #include "town_type.h" rubidium@8102: #include "road_func.h" rubidium@8108: #include "tile_map.h" tron@3069: tron@3146: rubidium@6248: enum RoadTileType { rubidium@3793: ROAD_TILE_NORMAL, rubidium@3793: ROAD_TILE_CROSSING, rubidium@3793: ROAD_TILE_DEPOT rubidium@6248: }; tron@3369: rubidium@3793: static inline RoadTileType GetRoadTileType(TileIndex t) rubidium@6661: { rubidium@7370: assert(IsTileType(t, MP_ROAD)); rubidium@6661: return (RoadTileType)GB(_m[t].m5, 6, 2); tron@3150: } tron@3150: 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@7370: return IsTileType(t, MP_ROAD) && IsLevelCrossing(t); Darkvater@3560: } tron@3150: rubidium@6661: static inline RoadBits GetRoadBits(TileIndex t, RoadType rt) tron@3272: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4); rubidium@6661: case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4); rubidium@6661: case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4); rubidium@6661: } tron@3369: } tron@3369: rubidium@6661: static inline RoadBits GetAllRoadBits(TileIndex tile) rubidium@6661: { rubidium@6661: return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY); rubidium@6661: } rubidium@6661: rubidium@6661: static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt) tron@3369: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); // XXX incomplete rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break; rubidium@6661: case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break; rubidium@6661: case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break; rubidium@6661: } tron@3369: } tron@3369: rubidium@6661: static inline RoadTypes GetRoadTypes(TileIndex t) rubidium@6661: { rubidium@7370: if (IsTileType(t, MP_ROAD)) { rubidium@6661: return (RoadTypes)GB(_me[t].m7, 5, 3); rubidium@6661: } else { rubidium@6661: return (RoadTypes)GB(_m[t].m3, 0, 3); rubidium@6661: } rubidium@6661: } rubidium@6661: rubidium@6661: static inline void SetRoadTypes(TileIndex t, RoadTypes rt) rubidium@6661: { rubidium@7370: if (IsTileType(t, MP_ROAD)) { rubidium@6661: SB(_me[t].m7, 5, 3, rt); rubidium@6661: } else { rubidium@6661: assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)); rubidium@6661: SB(_m[t].m3, 0, 2, rt); rubidium@6661: } rubidium@6661: } rubidium@6661: rubidium@6661: static inline Owner GetRoadOwner(TileIndex t, RoadType rt) rubidium@6661: { rubidium@7370: if (!IsTileType(t, MP_ROAD)) return GetTileOwner(t); rubidium@6661: rubidium@6661: switch (GetRoadTileType(t)) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROAD_TILE_NORMAL: rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5); rubidium@6764: case ROADTYPE_TRAM: { rubidium@6764: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@6764: * to OWNER_TOWN makes it use one bit less */ rubidium@6764: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@6764: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@6764: } rubidium@6661: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); rubidium@6661: } rubidium@6661: case ROAD_TILE_CROSSING: rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5); rubidium@6764: case ROADTYPE_TRAM: { rubidium@6764: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@6764: * to OWNER_TOWN makes it use one bit less */ rubidium@6764: Owner o = (Owner)GB( _m[t].m5, 0, 4); rubidium@6764: return o == OWNER_TOWN ? OWNER_NONE : o; rubidium@6764: } rubidium@6661: case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5); rubidium@6661: } rubidium@6661: case ROAD_TILE_DEPOT: return GetTileOwner(t); rubidium@6661: } rubidium@6661: } rubidium@6661: rubidium@6661: static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o) rubidium@6661: { rubidium@7370: if (!IsTileType(t, MP_ROAD)) return SetTileOwner(t, o); rubidium@6661: rubidium@6661: switch (GetRoadTileType(t)) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROAD_TILE_NORMAL: rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break; rubidium@6764: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; rubidium@6661: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; rubidium@6661: } rubidium@6662: break; rubidium@6661: case ROAD_TILE_CROSSING: rubidium@6661: switch (rt) { rubidium@6661: default: NOT_REACHED(); rubidium@6661: case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break; rubidium@6764: /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE rubidium@6764: * to OWNER_TOWN makes it use one bit less */ rubidium@6764: case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break; rubidium@6661: case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break; rubidium@6661: } rubidium@6662: break; rubidium@6661: case ROAD_TILE_DEPOT: return SetTileOwner(t, o); rubidium@6661: } rubidium@6661: } tron@3369: rubidium@6764: /** Which directions are disallowed ? */ rubidium@6764: enum DisallowedRoadDirections { rubidium@6764: DRD_NONE, ///< None of the directions are disallowed rubidium@6764: DRD_SOUTHBOUND, ///< All southbound traffic is disallowed rubidium@6764: DRD_NORTHBOUND, ///< All northbound traffic is disallowed rubidium@6764: DRD_BOTH, ///< All directions are disallowed rubidium@6764: DRD_END rubidium@6764: }; rubidium@6764: DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections); rubidium@6764: rubidium@6764: /** rubidium@6764: * Gets the disallowed directions rubidium@6764: * @param t the tile to get the directions from rubidium@6764: * @return the disallowed directions rubidium@6764: */ rubidium@6764: static inline DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t) rubidium@6764: { rubidium@6764: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); rubidium@6764: return (DisallowedRoadDirections)GB(_m[t].m5, 4, 2); rubidium@6764: } rubidium@6764: rubidium@6764: /** rubidium@6764: * Sets the disallowed directions rubidium@6764: * @param t the tile to set the directions for rubidium@6764: * @param drd the disallowed directions rubidium@6764: */ rubidium@6764: static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirections drd) rubidium@6764: { rubidium@6764: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); rubidium@6764: assert(drd < DRD_END); rubidium@6764: SB(_m[t].m5, 4, 2, drd); rubidium@6764: } rubidium@6764: tron@3369: static inline Axis GetCrossingRoadAxis(TileIndex t) tron@3369: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); rubidium@6661: return (Axis)GB(_m[t].m4, 6, 1); tron@3272: } tron@3272: 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: tron@3103: static inline TrackBits GetCrossingRailBits(TileIndex tile) tron@3103: { tron@4158: return AxisToTrackBits(OtherAxis(GetCrossingRoadAxis(tile))); tron@3103: } tron@3103: smatz@8344: static inline bool IsCrossingBarred(TileIndex t) smatz@8344: { smatz@8344: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); smatz@8344: return HasBit(_m[t].m4, 5); smatz@8344: } smatz@8344: smatz@8344: static inline void SetCrossingBarred(TileIndex t, bool barred) smatz@8344: { smatz@8344: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); smatz@8344: SB(_m[t].m4, 5, 1, barred); smatz@8344: } tron@3103: celestar@3322: static inline void UnbarCrossing(TileIndex t) celestar@3322: { smatz@8344: SetCrossingBarred(t, false); celestar@3322: } celestar@3322: celestar@3322: static inline void BarCrossing(TileIndex t) celestar@3322: { smatz@8344: SetCrossingBarred(t, true); celestar@3322: } tron@3274: celestar@3430: #define IsOnDesert IsOnSnow celestar@3430: static inline bool IsOnSnow(TileIndex t) celestar@3430: { skidd13@7928: 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@7932: ToggleBit(_m[t].m3, 7); celestar@3430: } celestar@3430: celestar@3430: rubidium@6248: 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@6248: }; celestar@3430: tron@4048: static inline Roadside GetRoadside(TileIndex tile) celestar@3430: { rubidium@6172: 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@6172: 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@6172: AB(_m[t].m3, 0, 4, 1); celestar@3430: rubidium@6172: 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@6172: SB(_m[t].m3, 0, 4, 0); celestar@3430: } celestar@3430: tron@3069: tron@3369: static inline DiagDirection GetRoadDepotDirection(TileIndex t) tron@3069: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_DEPOT); 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@6390: * 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@6418: * @param tile the tile to get the road bits for rubidium@6661: * @param rt the road type to get the road bits form rubidium@6418: * @return the road bits of the given tile tron@3146: */ rubidium@6661: RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt); tron@3146: rubidium@6418: /** rubidium@6418: * Get the accessible track bits for the given tile. rubidium@6418: * Special behaviour: rubidium@6418: * - road depots: no track bits rubidium@6418: * - non-drive-through stations: no track bits rubidium@6418: * @param tile the tile to get the track bits for rubidium@6418: * @return the track bits for the given tile rubidium@6418: */ rubidium@6661: TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt); tron@3150: rubidium@8102: /** rubidium@8102: * Return if the tile is a valid tile for a crossing. rubidium@8102: * rubidium@8102: * @note function is overloaded rubidium@8102: * @param tile the curent tile rubidium@8102: * @param ax the axis of the road over the rail rubidium@8102: * @return true if it is a valid tile rubidium@8102: */ rubidium@8102: bool IsPossibleCrossing(const TileIndex tile, Axis ax); rubidium@8102: tron@3150: rubidium@6661: static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway) tron@3099: { rubidium@7370: SetTileType(t, MP_ROAD); rubidium@6661: SetTileOwner(t, road); tron@3099: _m[t].m2 = town; rubidium@6661: _m[t].m3 = 0; skidd13@7928: _m[t].m4 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0) << 4 | (HasBit(rot, ROADTYPE_ROAD) ? bits : 0); rubidium@6778: _m[t].m5 = ROAD_TILE_NORMAL << 6; rubidium@6778: SetRoadOwner(t, ROADTYPE_TRAM, tram); skidd13@7928: SB(_m[t].m6, 2, 4, HasBit(rot, ROADTYPE_HWAY) ? bits : 0); rubidium@6661: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: rubidium@6661: 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@7370: SetTileType(t, MP_ROAD); tron@3099: SetTileOwner(t, rail); tron@3099: _m[t].m2 = town; rubidium@6661: _m[t].m3 = rat; rubidium@6661: _m[t].m4 = roaddir << 6 | road; rubidium@6778: _m[t].m5 = ROAD_TILE_CROSSING << 6; rubidium@6778: SetRoadOwner(t, ROADTYPE_TRAM, tram); rubidium@6661: SB(_m[t].m6, 2, 4, 0); rubidium@6661: _me[t].m7 = rot << 5 | hway; tron@3099: } tron@3099: tron@3099: rubidium@6661: static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, RoadType rt) tron@3099: { rubidium@7370: 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@6661: _m[t].m5 = ROAD_TILE_DEPOT << 6 | dir; rubidium@6661: SB(_m[t].m6, 2, 4, 0); rubidium@6661: _me[t].m7 = RoadTypeToRoadTypes(rt) << 5; tron@3099: } tron@3099: peter1138@4666: #endif /* ROAD_MAP_H */