tron@3069: /* $Id$ */ tron@3069: glx@9574: /** @file road_map.h */ glx@9574: tron@3145: #ifndef ROAD_MAP_H tron@3145: #define ROAD_MAP_H tron@3069: tron@3069: #include "macros.h" tron@3099: #include "rail.h" tron@3518: #include "road.h" tron@3099: #include "tile.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@9624: { rubidium@9694: assert(IsTileType(t, MP_ROAD)); glx@9624: 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@9694: return IsTileType(t, MP_ROAD) && IsLevelCrossing(t); Darkvater@3560: } tron@3150: glx@9624: static inline RoadBits GetRoadBits(TileIndex t, RoadType rt) tron@3272: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); 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: 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: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); // 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@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@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: { rubidium@9625: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); 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: { rubidium@9625: assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); 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: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); glx@9624: 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: tron@3103: celestar@3322: static inline void UnbarCrossing(TileIndex t) celestar@3322: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); glx@9624: CLRBIT(_m[t].m4, 5); celestar@3322: } celestar@3322: celestar@3322: static inline void BarCrossing(TileIndex t) celestar@3322: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); glx@9624: SETBIT(_m[t].m4, 5); celestar@3322: } celestar@3322: celestar@3322: static inline bool IsCrossingBarred(TileIndex t) celestar@3322: { rubidium@3793: assert(GetRoadTileType(t) == ROAD_TILE_CROSSING); glx@9624: return HASBIT(_m[t].m4, 5); celestar@3322: } tron@3274: celestar@3430: #define IsOnDesert IsOnSnow celestar@3430: static inline bool IsOnSnow(TileIndex t) celestar@3430: { rubidium@6498: 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@6498: 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: { 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 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 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 glx@9574: * @return the road bits of the given tile tron@3146: */ glx@9624: RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt); 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: 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; glx@9624: _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); glx@9624: 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 */