/** * Finds the distance for the closest tile with water/land given a tile * @param tile the tile to find the distance too * @param water whether to find water or land * @return distance to nearest water (max 0x7F) / land (max 0x1FF; 0x200 if there is no land) */ uint GetClosestWaterDistance(TileIndex tile, bool water) { if (WaterMap.HasTileWaterGround(tile) == water) { return(0); } uint max_dist = (uint)(water ? 0x7F : 0x200); int x = (int)TileX(tile); int y = (int)TileY(tile); uint max_x = MapMaxX(); uint max_y = MapMaxY(); uint min_xy = (uint)(_settings_game.construction.freeform_edges ? 1 : 0); /* go in a 'spiral' with increasing manhattan distance in each iteration */ for (uint dist = 1; dist < max_dist; dist++) { /* next 'diameter' */ y--; /* going counter-clockwise around this square */ for (var dir = (int)DiagDirection.DIAGDIR_BEGIN; dir < (int)DiagDirection.DIAGDIR_END; dir++) { int dx = ddx[dir]; int dy = ddy[dir]; /* each side of this square has length 'dist' */ for (uint a = 0; a < dist; a++) { /* MP_VOID tiles are not checked (interval is [min; max) for IsInsideMM())*/ if (MathFuncs.IsInsideMM(x, min_xy, max_x) && MathFuncs.IsInsideMM(y, min_xy, max_y)) { TileIndex t = TileXY((uint)x, (uint)y); if (WaterMap.HasTileWaterGround(t) == water) { return(dist); } } x += dx; y += dy; } } } if (!water) { /* no land found - is this a water-only map? */ for (TileIndex t = 0; t < MapSize(); t++) { if (!TileMap.IsTileType(t, TileType.MP_VOID) && !TileMap.IsTileType(t, TileType.MP_WATER)) { return(0x1FF); } } } return(max_dist); }
/** * Get the water tile type at a tile. * @param t Water tile to query. * @return Water tile type at the tile. */ //inline public static WaterTileType GetWaterTileType(TileIndex t) { if (TileMap.IsTileType(t, TileType.MP_WATER) == false) { throw new ArgumentException(nameof(t), "Supplied tile must be of type MP_WATER"); } switch ((WaterTileTypeBitLayout)BitMath.GB(Map._m[t].m5, (byte)WaterTileTypeBitLayout.WBL_TYPE_BEGIN, (byte)WaterTileTypeBitLayout.WBL_TYPE_COUNT)) { case WaterTileTypeBitLayout.WBL_TYPE_NORMAL: return(BitMath.HasBit(Map._m[t].m5, (byte)WaterTileTypeBitLayout.WBL_COAST_FLAG) ? WaterTileType.WATER_TILE_COAST : WaterTileType.WATER_TILE_CLEAR); case WaterTileTypeBitLayout.WBL_TYPE_LOCK: return(WaterTileType.WATER_TILE_LOCK); case WaterTileTypeBitLayout.WBL_TYPE_DEPOT: return(WaterTileType.WATER_TILE_DEPOT); default: throw new NotReachedException(); } }
/** * Return if the tile is a valid tile for a crossing. * * @param tile the current tile * @param ax the axis of the road over the rail * @return true if it is a valid tile */ static bool IsPossibleCrossing(TileIndex tile, Axis ax) { return(TileMap.IsTileType(tile, TileType.MP_RAILWAY) && GetRailTileType(tile) == RAIL_TILE_NORMAL && GetTrackBits(tile) == (ax == Axis.AXIS_X ? TrackBits.TRACK_BIT_Y : TrackBits.TRACK_BIT_X) && GetFoundationSlope(tile) == Slope.SLOPE_FLAT); }
/** * Increments the age of the house. * @param t the tile of this house * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void IncrementHouseAge(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); if (IsHouseCompleted(t) && Map._m[t].m5 < 0xFF) { Map._m[t].m5++; } }
/** * Get the random bits of the water tile. * @param t Water tile to query. * @return Random bits of the tile. * @pre IsTileType(t, MP_WATER) */ /*inline*/ public static byte GetWaterTileRandomBits(TileIndex t) { if (TileMap.IsTileType(t, TileType.MP_WATER) == false) { throw new ArgumentException(nameof(t)); } return(Map._m[t].m4); }
/** * Sets the increment stage of a house * It is working with the whole counter + stage 5 bits, making it * easier to work: the wraparound is automatic. * @param t the tile of the house to increment the construction stage of * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void IncHouseConstructionTick(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); Map._m[t].m5 = BitMath.AB(Map._m[t].m5, 0, 5, 1); if (BitMath.GB(Map._m[t].m5, 3, 2) == TOWN_HOUSE_COMPLETED) { /* House is now completed. * Store the year of construction as well, for newgrf house purpose */ SetHouseCompleted(t, true); } }
/** * Make the tile a house. * @param t tile index * @param tid Town index * @param counter of construction step * @param stage of construction (used for drawing) * @param type of house. Index into house specs array * @param random_bits required for newgrf houses * @pre TileMap.IsTileType(t, MP_CLEAR) */ public static void MakeHouseTile(this TileIndex t, ushort tid, byte counter, byte stage, HouseID type, byte random_bits) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_CLEAR)); TileMap.SetTileType(t, TileType.MP_HOUSE); Map._m[t].m1 = random_bits; Map._m[t].m2 = tid; Map._m[t].m3 = 0; SetHouseType(t, type); SetHouseCompleted(t, stage == TOWN_HOUSE_COMPLETED); Map._m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter); SetAnimationFrame(t, 0); SetHouseProcessingTime(t, HouseSpec.Get(type).processing_time); }
/** * Get the tileoffset from this tile a ship should target to get to this dock. * @param t Tile to query * @pre TileMap.IsTileType(t, TileType.MP_STATION) * @pre IsBuoy(t) || IsOilRig(t) || IsDock(t) * @return The offset from this tile that should be used as destination for ships. */ public static TileIndexDiffC GetDockOffset(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_STATION)); if (IsBuoy(t)) { return(buoy_offset); } if (IsOilRig(t)) { return(oilrig_offset); } Debug.Assert(IsDock(t)); return(dock_offset[t.GetDockDirection()]); }
/** * Get the owner of a specific road type. * @param t The tile to query. * @param rt The road type to get the owner of. * @return Owner of the given road type. */ public static Owner GetRoadOwner(this TileIndex t, RoadType rt) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_ROAD) || TileMap.IsTileType(t, TileType.MP_STATION) || TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); switch (rt) { default: throw new NotReachedException(); case RoadType.ROADTYPE_ROAD: return((Owner)BitMath.GB(IsNormalRoadTile(t) ? Map._m[t].m1 : Map._me[t].m7, 0, 5)); case RoadType.ROADTYPE_TRAM: { /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE * to OWNER_TOWN makes it use one bit less */ Owner o = (Owner)BitMath.GB(Map._m[t].m3, 4, 4); return(o == Owner.OWNER_TOWN ? Owner.OWNER_NONE : o); } } }
/** * Get the index of which town this house/street is attached to. * @param t the tile * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) or TileMap.IsTileType(t, TileType.MP_ROAD) but not a road depot * @return TownID */ public static TownID GetTownIndex(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE) || (TileMap.IsTileType(t, TileType.MP_ROAD) && !t.IsRoadDepot())); return(Map._m[t].m2); }
/** * Decrease the amount of time remaining before the tile loop processes this tile. * @param t the house tile * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void DecHouseProcessingTime(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); Map._me[t].m6 -= 1 << 2; }
/** * Set the amount of time remaining before the tile loop processes this tile. * @param t the house tile * @param time the time to be set * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void SetHouseProcessingTime(this TileIndex t, byte time) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); BitMath.SB(Map._me[t].m6, 2, 6, time); }
/** * Get the amount of time remaining before the tile loop processes this tile. * @param t the house tile * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return time remaining */ public static byte GetHouseProcessingTime(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(BitMath.GB(Map._me[t].m6, 2, 6)); }
/** * Determines type of the wormhole and returns its other end * @param t one end * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) * @return other end */ public static TileIndex GetOtherTunnelBridgeEnd(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); return(t.IsTunnel() ? t.GetOtherTunnelEnd() : GetOtherBridgeEnd(t)); }
/** * Tunnel: Is this tunnel entrance in a snowy or desert area? * Bridge: Does the bridge ramp lie in a snow or desert area? * @param t The tile to analyze * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) * @return true if and only if the tile is in a snowy/desert area */ public static bool HasTunnelBridgeSnowOrDesert(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); return(BitMath.HasBit(Map._me[t].m7, 5)); }
/** * Get the direction pointing to the other end. * * Tunnel: Get the direction facing into the tunnel * Bridge: Get the direction pointing onto the bridge * @param t The tile to analyze * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) * @return the above mentioned direction */ public static DiagDirection GetTunnelBridgeDirection(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); return((DiagDirection)BitMath.GB(Map._m[t].m5, 0, 2)); }
/** * Set the house type. * @param t the tile * @param house_id the new house type * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void SetHouseType(this TileIndex t, HouseID house_id) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); Map._m[t].m4 = BitMath.GB(house_id, 0, 8); Map._m[t].m3 = BitMath.SB(Map._m[t].m3, 6, 1, BitMath.GB(house_id, 8, 1)); }
/** * Set the town index for a road or house tile. * @param t the tile * @param index the index of the town * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) or TileMap.IsTileType(t, TileType.MP_ROAD) but not a road depot */ public static void SetTownIndex(this TileIndex t, TownID index) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE) || (TileMap.IsTileType(t, TileType.MP_ROAD) && !t.IsRoadDepot())); Map._m[t].m2 = index; }
/** * Sets the age of the house to zero. * Needs to be called after the house is completed. During construction stages the map space is used otherwise. * @param t the tile of this house * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) && IsHouseCompleted(t) */ public static void ResetHouseAge(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE) && IsHouseCompleted(t)); Map._m[t].m5 = 0; }
/** * Gets the construction stage of a house * @param t the tile of the house to get the construction stage of * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return the construction stage of the house */ public static byte GetHouseConstructionTick(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(IsHouseCompleted(t) ? 0 : BitMath.GB(Map._m[t].m5, 0, 3)); }
/** * Get the type of this house, which is an index into the house spec array * without doing any NewGRF related translations. * @param t the tile * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return house type */ public static HouseID GetCleanHouseType(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(Map._m[t].m4 | (BitMath.GB(Map._m[t].m3, 6, 1) << 8)); }
/** * Get the age of the house * @param t the tile of this house * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return year */ public static Year GetHouseAge(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(IsHouseCompleted(t) ? Map._m[t].m5 : 0); }
/** * Set the reservation state of the rail tunnel/bridge * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @param b the reservation state */ public static void SetTunnelBridgeReservation(this TileIndex t, bool b) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); Debug.Assert(GetTunnelBridgeTransportType(t) == TransportType.TRANSPORT_RAIL); Map._m[t].m5 = BitMath.SB(Map._m[t].m5, 4, 1, b ? 1 : 0); }
/** * Set the random bits for this house. * This is required for newgrf house * @param t the tile of this house * @param random the new random bits * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void SetHouseRandomBits(this TileIndex t, byte random) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); Map._m[t].m1 = random; }
/** * Tunnel: Get the transport type of the tunnel (road or rail) * Bridge: Get the transport type of the bridge's ramp * @param t The tile to analyze * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) * @return the transport type in the tunnel/bridge */ public static TransportType GetTunnelBridgeTransportType(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); return((TransportType)BitMath.GB(Map._m[t].m5, 2, 2)); }
/** * Get the random bits for this house. * This is required for newgrf house * @param t the tile of this house * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return random bits */ public static byte GetHouseRandomBits(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(Map._m[t].m1); }
/** * Tunnel: Places this tunnel entrance in a snowy or desert area, or takes it out of there. * Bridge: Sets whether the bridge ramp lies in a snow or desert area. * @param t the tunnel entrance / bridge ramp tile * @param snow_or_desert is the entrance/ramp in snow or desert (true), when * not in snow and not in desert false * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) */ public static void SetTunnelBridgeSnowOrDesert(this TileIndex t, bool snow_or_desert) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); Map._me[t].m7 = BitMath.SB(Map._me[t].m7, 5, 1, snow_or_desert); }
/** * Set the activated triggers bits for this house. * This is required for newgrf house * @param t the tile of this house * @param triggers the activated triggers * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) */ public static void SetHouseTriggers(this TileIndex t, byte triggers) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); BitMath.SB(Map._m[t].m3, 0, 5, triggers); }
/** * Get the reservation state of the rail tunnel/bridge * @pre TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reservation state */ public static bool HasTunnelBridgeReservation(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_TUNNELBRIDGE)); Debug.Assert(GetTunnelBridgeTransportType(t) == TransportType.TRANSPORT_RAIL); return(BitMath.HasBit(Map._m[t].m5, 4)); }
/** * Get the already activated triggers bits for this house. * This is required for newgrf house * @param t the tile of this house * @pre TileMap.IsTileType(t, TileType.MP_HOUSE) * @return triggers */ public static byte GetHouseTriggers(this TileIndex t) { Debug.Assert(TileMap.IsTileType(t, TileType.MP_HOUSE)); return(BitMath.GB(Map._m[t].m3, 0, 5)); }