Changeset - r9341:c8e34c3b896e
[Not reviewed]
master
0 6 0
frosch - 16 years ago 2008-05-24 19:36:20
frosch@openttd.org
(svn r13233) -Fix: Replace some (incorrect) evaluations of TileOwner by RoadOwner.
-Fix: Before evaluating RoadOwner, check if the roadtype is present.
-Fix: Some places assumed that MP_ROAD means normal street.
6 files changed with 34 insertions and 28 deletions:
0 comments (0 inline, 0 general)
src/ai/default/default.cpp
Show inline comments
 
@@ -3718,101 +3718,101 @@ pos_0:
 
				if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(1, 0))) & TRACK_BIT_3WAY_SW) == 0) {
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_NE;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_SE) {
 
pos_1:
 
				if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(0, 1))) & TRACK_BIT_3WAY_NW) == 0) {
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_SE;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_SW) {
 
pos_2:
 
				if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(1, 0))) & TRACK_BIT_3WAY_NE) == 0) {
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_SW;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_NW) {
 
pos_3:
 
				if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(0, 1))) & TRACK_BIT_3WAY_SE) == 0) {
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_NW;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 
		} else {
 
			static const byte _depot_bits[] = {0x19, 0x16, 0x25, 0x2A};
 

	
 
			DiagDirection dir = GetRailDepotDirection(tile);
 

	
 
			if (GetRailTrackStatus(tile + TileOffsByDiagDir(dir)) & _depot_bits[dir])
 
				return;
 

	
 
			DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		}
 
	} else if (IsTileType(tile, MP_ROAD)) {
 
		if (!IsTileOwner(tile, _current_player)) return;
 

	
 
		if (IsLevelCrossing(tile)) goto is_rail_crossing;
 

	
 
		if (IsRoadDepot(tile)) {
 
			if (!IsTileOwner(tile, _current_player)) return;
 

	
 
			DiagDirection dir;
 
			TileIndex t;
 

	
 
			// Check if there are any stations around.
 
			t = tile + TileDiffXY(-1, 0);
 
			if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
 

	
 
			t = tile + TileDiffXY(1, 0);
 
			if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
 

	
 
			t = tile + TileDiffXY(0, -1);
 
			if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
 

	
 
			t = tile + TileDiffXY(0, 1);
 
			if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
 

	
 
			dir = GetRoadDepotDirection(tile);
 

	
 
			DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
			DoCommand(
 
				TILE_MASK(tile + TileOffsByDiagDir(dir)),
 
				DiagDirToRoadBits(ReverseDiagDir(dir)),
 
				0,
 
				DC_EXEC,
 
				CMD_REMOVE_ROAD);
 
		}
 
	} else if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
		if (!IsTileOwner(tile, _current_player) ||
 
				!IsBridge(tile) ||
 
				GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) {
 
			return;
 
		}
 

	
 
		rails = TRACK_BIT_NONE;
 

	
 
		switch (GetTunnelBridgeDirection(tile)) {
 
			default:
 
			case DIAGDIR_NE: goto pos_2;
 
			case DIAGDIR_SE: goto pos_3;
 
			case DIAGDIR_SW: goto pos_0;
 
			case DIAGDIR_NW: goto pos_1;
 
		}
 
	}
 
}
 

	
 
static void AiStateRemoveTrack(Player *p)
 
{
 
	/* Was 1000 for standard 8x8 maps. */
src/road_cmd.cpp
Show inline comments
 
@@ -128,144 +128,139 @@ static const RoadBits _invalid_tileh_slo
 
	}
 
};
 

	
 
Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
 

	
 
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
 
{
 
	*edge_road = true;
 

	
 
	if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
 

	
 
	/* Water can always flood and towns can always remove "normal" road pieces.
 
	 * Towns are not be allowed to remove non "normal" road pieces, like tram
 
	 * tracks as that would result in trams that cannot turn. */
 
	if (_current_player == OWNER_WATER ||
 
			(rt == ROADTYPE_ROAD && !IsValidPlayer(_current_player))) return true;
 

	
 
	/* Only do the special processing if the road is owned
 
	 * by a town */
 
	if (owner != OWNER_TOWN) return (owner == OWNER_NONE) || CheckOwnership(owner);
 

	
 
	if (_cheats.magic_bulldozer.value) return true;
 

	
 
	/* Get a bitmask of which neighbouring roads has a tile */
 
	RoadBits n = ROAD_NONE;
 
	RoadBits present = GetAnyRoadBits(tile, rt);
 
	if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1,  0), rt) & ROAD_SW) n |= ROAD_NE;
 
	if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile,  0,  1), rt) & ROAD_NW) n |= ROAD_SE;
 
	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile,  1,  0), rt) & ROAD_NE) n |= ROAD_SW;
 
	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile,  0, -1), rt) & ROAD_SE) n |= ROAD_NW;
 

	
 
	/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
 
	 * then allow it */
 
	if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
 
		*edge_road = false;
 
		/* you can remove all kind of roads with extra dynamite */
 
		if (_patches.extra_dynamite) return true;
 

	
 
		const Town *t = ClosestTownFromTile(tile, (uint)-1);
 

	
 
		SetDParam(0, t->index);
 
		_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
 
{
 
	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
 
}
 

	
 

	
 
/** Delete a piece of road.
 
 * @param tile tile where to remove road from
 
 * @param flags operation to perform
 
 * @param pieces roadbits to remove
 
 * @param rt roadtype to remove
 
 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
 
 */
 
static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
 
{
 
	/* cost for removing inner/edge -roads */
 
	static const uint16 road_remove_cost[2] = {50, 18};
 

	
 
	/* true if the roadpiece was always removeable,
 
	 * false if it was a center piece. Affects town ratings drop */
 
	bool edge_road;
 

	
 
	RoadTypes rts = GetRoadTypes(tile);
 
	/* The tile doesn't have the given road type */
 
	if (!HasBit(rts, rt)) return CMD_ERROR;
 

	
 
	Town *t = NULL;
 
	switch (GetTileType(tile)) {
 
		case MP_ROAD:
 
			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
 
			if (_game_mode != GM_EDITOR && IsRoadOwner(tile, rt, OWNER_TOWN)) t = GetTownByTile(tile);
 
			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
			break;
 

	
 
		case MP_STATION:
 
			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
 
			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
			break;
 

	
 
		case MP_TUNNELBRIDGE:
 
			if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
 
			if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR;
 
			break;
 

	
 
		default:
 
			return CMD_ERROR;
 
	}
 

	
 
	RoadTypes rts = GetRoadTypes(tile);
 
	/* The tile doesn't have the given road type */
 
	if (!HasBit(rts, rt)) return CMD_ERROR;
 

	
 
	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
 
	if (!CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), &edge_road, rt)) return CMD_ERROR;
 

	
 
	/* check if you're allowed to remove the street owned by a town
 
	 * removal allowance depends on difficulty setting */
 
	if (town_check && !CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
 

	
 
	if (!IsTileType(tile, MP_ROAD)) {
 
		/* If it's the last roadtype, just clear the whole tile */
 
		if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 

	
 
		CommandCost cost(EXPENSES_CONSTRUCTION);
 
		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
			TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
 
			/* Pay for *every* tile of the bridge or tunnel */
 
			cost.AddCost((GetTunnelBridgeLength(other_end, tile) + 2) * _price.remove_road);
 
			if (flags & DC_EXEC) {
 
				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
 
				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
 

	
 
				/* Mark tiles diry that have been repaved */
 
				MarkTileDirtyByTile(tile);
 
				MarkTileDirtyByTile(other_end);
 
				if (IsBridge(tile)) {
 
					TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
 

	
 
					for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t);
 
				}
 
			}
 
		} else {
 
			cost.AddCost(_price.remove_road);
 
			if (flags & DC_EXEC) {
 
				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
 
				MarkTileDirtyByTile(tile);
 
			}
 
		}
 
		return cost;
 
	}
 

	
 
	switch (GetRoadTileType(tile)) {
 
		case ROAD_TILE_NORMAL: {
 
			const Slope tileh = GetTileSlope(tile, NULL);
 
			RoadBits present = GetRoadBits(tile, rt);
 
			const RoadBits other = GetOtherRoadBits(tile, rt);
 
			const Foundation f = GetRoadFoundation(tileh, present);
 

	
 
			if (HasRoadWorks(tile) && _current_player != OWNER_WATER) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
 

	
 
			/* Autocomplete to a straight road
 
			 * @li on steep slopes
 
@@ -456,97 +451,97 @@ static CommandCost CheckRoadSlope(Slope 
 
/** Build a piece of road.
 
 * @param tile tile where to build road
 
 * @param flags operation to perform
 
 * @param p1 bit 0..3 road pieces to build (RoadBits)
 
 *           bit 4..5 road type
 
 *           bit 6..7 disallowed directions to toggle
 
 * @param p2 the town that is building the road (0 if not applicable)
 
 */
 
CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 

	
 
	RoadBits existing = ROAD_NONE;
 
	RoadBits other_bits = ROAD_NONE;
 

	
 
	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
 
	 * if a non-player is building the road */
 
	if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
 

	
 
	RoadBits pieces = Extract<RoadBits, 0>(p1);
 

	
 
	/* do not allow building 'zero' road bits, code wouldn't handle it */
 
	if (pieces == ROAD_NONE) return CMD_ERROR;
 

	
 
	RoadType rt = (RoadType)GB(p1, 4, 2);
 
	if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
 

	
 
	DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2);
 

	
 
	Slope tileh = GetTileSlope(tile, NULL);
 

	
 
	switch (GetTileType(tile)) {
 
		case MP_ROAD:
 
			switch (GetRoadTileType(tile)) {
 
				case ROAD_TILE_NORMAL: {
 
					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
 

	
 
					other_bits = GetOtherRoadBits(tile, rt);
 
					if (!HasTileRoadType(tile, rt)) break;
 

	
 
					existing = GetRoadBits(tile, rt);
 
					bool crossing = !IsStraightRoad(existing | pieces);
 
					if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
 
						/* Junctions cannot be one-way */
 
						return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
 
					}
 
					if ((existing & pieces) == pieces) {
 
						/* We only want to set the (dis)allowed road directions */
 
						if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && GetRoadOwner(tile, ROADTYPE_ROAD) == _current_player) {
 
						if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && IsRoadOwner(tile, ROADTYPE_ROAD, _current_player)) {
 
							if (crossing) return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
 

	
 
							if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 

	
 
							/* Ignore half built tiles */
 
							if (flags & DC_EXEC && rt != ROADTYPE_TRAM && IsStraightRoad(existing)) {
 
								SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd);
 
								MarkTileDirtyByTile(tile);
 
							}
 
							return CommandCost();
 
						}
 
						return_cmd_error(STR_1007_ALREADY_BUILT);
 
					}
 
				} break;
 

	
 
				case ROAD_TILE_CROSSING:
 
					if (HasTileRoadType(tile, rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
 
					other_bits = GetCrossingRoadBits(tile);
 
					if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
 
					break;
 

	
 
				default:
 
				case ROAD_TILE_DEPOT:
 
					goto do_clear;
 
			}
 
			break;
 

	
 
		case MP_RAILWAY: {
 
			if (IsSteepSlope(tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 

	
 
			/* Level crossings may only be built on these slopes */
 
			if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 

	
 
			if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
 

	
 
			Axis roaddir;
 
			switch (GetTrackBits(tile)) {
 
				case TRACK_BIT_X:
 
					if (pieces & ROAD_X) goto do_clear;
 
					roaddir = AXIS_Y;
 
					break;
 

	
 
				case TRACK_BIT_Y:
 
					if (pieces & ROAD_Y) goto do_clear;
 
@@ -849,97 +844,97 @@ CommandCost CmdBuildRoadDepot(TileIndex 
 
	if (tileh != SLOPE_FLAT && (
 
				!_patches.build_on_slopes ||
 
				IsSteepSlope(tileh) ||
 
				!CanBuildDepotByTileh(dir, tileh)
 
			)) {
 
		return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 
	}
 

	
 
	CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(cost)) return CMD_ERROR;
 

	
 
	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	if (!Depot::CanAllocateItem()) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		Depot *dep = new Depot(tile);
 
		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 

	
 
		MakeRoadDepot(tile, _current_player, dir, rt);
 
		MarkTileDirtyByTile(tile);
 
	}
 
	return cost.AddCost(_price.build_road_depot);
 
}
 

	
 
static CommandCost RemoveRoadDepot(TileIndex tile, uint32 flags)
 
{
 
	if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
 

	
 
	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DoClearSquare(tile);
 
		delete GetDepotByTile(tile);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_road_depot);
 
}
 

	
 
static CommandCost ClearTile_Road(TileIndex tile, byte flags)
 
{
 
	switch (GetRoadTileType(tile)) {
 
		case ROAD_TILE_NORMAL: {
 
			RoadBits b = GetAllRoadBits(tile);
 

	
 
			/* Clear the road if only one piece is on the tile OR the AI tries
 
			 * to clear town road OR we are not using the DC_AUTO flag */
 
			if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) ||
 
			    ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) ||
 
			    ((flags & DC_AI_BUILDING) && GetOtherRoadBits(tile, ROADTYPE_ROAD) == ROAD_NONE && IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) ||
 
			    !(flags & DC_AUTO)
 
				) {
 
				RoadTypes rts = GetRoadTypes(tile);
 
				CommandCost ret(EXPENSES_CONSTRUCTION);
 
				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 
					if (HasBit(rts, rt)) {
 
						CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
 
						if (CmdFailed(tmp_ret)) return tmp_ret;
 
						ret.AddCost(tmp_ret);
 
					}
 
				}
 
				return ret;
 
			}
 
			return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
 
		}
 

	
 
		case ROAD_TILE_CROSSING: {
 
			RoadTypes rts = GetRoadTypes(tile);
 
			CommandCost ret(EXPENSES_CONSTRUCTION);
 

	
 
			if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
 

	
 
			/* Must iterate over the roadtypes in a reverse manner because
 
			 * tram tracks must be removed before the road bits. */
 
			RoadType rt = ROADTYPE_HWAY;
 
			do {
 
				if (HasBit(rts, rt)) {
 
					CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false);
 
					if (CmdFailed(tmp_ret)) return tmp_ret;
 
					ret.AddCost(tmp_ret);
 
				}
 
			} while (rt-- != ROADTYPE_ROAD);
 

	
 
			if (flags & DC_EXEC) {
 
				DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			}
 
			return ret;
 
		}
 

	
 
		default:
 
		case ROAD_TILE_DEPOT:
 
			if (flags & DC_AUTO) {
 
				return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
 
			}
 
			return RemoveRoadDepot(tile, flags);
 
	}
 
}
 

	
 
@@ -1504,99 +1499,97 @@ static const byte _roadveh_enter_depot_d
 
	TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE
 
};
 

	
 
static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y)
 
{
 
	switch (GetRoadTileType(tile)) {
 
		case ROAD_TILE_CROSSING:
 
			if (v->type == VEH_TRAIN) {
 
				/* it should be barred */
 
				assert(IsCrossingBarred(tile));
 
			}
 
			break;
 

	
 
		case ROAD_TILE_DEPOT:
 
			if (v->type == VEH_ROAD &&
 
					v->u.road.frame == 11 &&
 
					_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) {
 
				v->u.road.state = RVSB_IN_DEPOT;
 
				v->vehstatus |= VS_HIDDEN;
 
				v->direction = ReverseDir(v->direction);
 
				if (v->Next() == NULL) VehicleEnterDepot(v);
 
				v->tile = tile;
 

	
 
				InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
				return VETSB_ENTERED_WORMHOLE;
 
			}
 
			break;
 

	
 
		default: break;
 
	}
 
	return VETSB_CONTINUE;
 
}
 

	
 

	
 
static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
 
{
 
	if (IsRoadDepot(tile)) {
 
		if (GetTileOwner(tile) == old_player) {
 
			if (new_player == PLAYER_SPECTATOR) {
 
				DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
 
			} else {
 
				SetTileOwner(tile, new_player);
 
			}
 
		}
 
		return;
 
	}
 

	
 
	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 
		/* ROADTYPE_ROAD denotes the tile owner, so update it too */
 
		if (rt != ROADTYPE_ROAD && !HasTileRoadType(tile, rt)) continue;
 

	
 
		/* Update all roadtypes, no matter if they are present */
 
		if (GetRoadOwner(tile, rt) == old_player) {
 
			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
 
		}
 
	}
 

	
 
	if (IsLevelCrossing(tile)) {
 
		if (GetTileOwner(tile) == old_player) {
 
			if (new_player == PLAYER_SPECTATOR) {
 
				DoCommand(tile, 0, GetCrossingRailTrack(tile), DC_EXEC | DC_BANKRUPT, CMD_REMOVE_SINGLE_RAIL);
 
			} else {
 
				SetTileOwner(tile, new_player);
 
			}
 
		}
 
	}
 
}
 

	
 
static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 
{
 
	if (_patches.build_on_slopes && AutoslopeEnabled()) {
 
		switch (GetRoadTileType(tile)) {
 
			case ROAD_TILE_CROSSING:
 
				if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
				break;
 

	
 
			case ROAD_TILE_DEPOT:
 
				if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
				break;
 

	
 
			case ROAD_TILE_NORMAL: {
 
				RoadBits bits = GetAllRoadBits(tile);
 
				RoadBits bits_copy = bits;
 
				/* Check if the slope-road_bits combination is valid at all, i.e. it is save to call GetRoadFoundation(). */
 
				if (!CmdFailed(CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE))) {
 
					/* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
 
					if (bits == bits_copy) {
 
						uint z_old;
 
						Slope tileh_old = GetTileSlope(tile, &z_old);
 

	
 
						/* Get the slope on top of the foundation */
 
						z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
 
						z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
 

	
 
						/* The surface slope must not be changed */
 
						if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
					}
 
				}
 
				break;
 
			}
src/road_map.h
Show inline comments
 
@@ -142,96 +142,102 @@ static inline Owner GetRoadOwner(TileInd
 
					return o == OWNER_TOWN ? OWNER_NONE : o;
 
				}
 
				case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
 
			}
 
		case ROAD_TILE_CROSSING:
 
			switch (rt) {
 
				default: NOT_REACHED();
 
				case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5);
 
				case ROADTYPE_TRAM: {
 
					/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
 
					 * to OWNER_TOWN makes it use one bit less */
 
					Owner o = (Owner)GB( _m[t].m5, 0, 4);
 
					return o == OWNER_TOWN ? OWNER_NONE : o;
 
				}
 
				case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
 
			}
 
		case ROAD_TILE_DEPOT: return GetTileOwner(t);
 
	}
 
}
 

	
 
static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
 
{
 
	if (!IsTileType(t, MP_ROAD)) return SetTileOwner(t, o);
 

	
 
	switch (GetRoadTileType(t)) {
 
		default: NOT_REACHED();
 
		case ROAD_TILE_NORMAL:
 
			switch (rt) {
 
				default: NOT_REACHED();
 
				case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break;
 
				case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
 
				case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
 
			}
 
			break;
 
		case ROAD_TILE_CROSSING:
 
			switch (rt) {
 
				default: NOT_REACHED();
 
				case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break;
 
				/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
 
				 * to OWNER_TOWN makes it use one bit less */
 
				case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
 
				case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
 
			}
 
			break;
 
		case ROAD_TILE_DEPOT: return SetTileOwner(t, o);
 
	}
 
}
 

	
 
static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o)
 
{
 
	assert(HasTileRoadType(t, rt));
 
	return (GetRoadOwner(t, rt) == o);
 
}
 

	
 
/** Which directions are disallowed ? */
 
enum DisallowedRoadDirections {
 
	DRD_NONE,       ///< None of the directions are disallowed
 
	DRD_SOUTHBOUND, ///< All southbound traffic is disallowed
 
	DRD_NORTHBOUND, ///< All northbound traffic is disallowed
 
	DRD_BOTH,       ///< All directions are disallowed
 
	DRD_END
 
};
 
DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections);
 

	
 
/**
 
 * Gets the disallowed directions
 
 * @param t the tile to get the directions from
 
 * @return the disallowed directions
 
 */
 
static inline DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t)
 
{
 
	assert(IsNormalRoad(t));
 
	return (DisallowedRoadDirections)GB(_m[t].m5, 4, 2);
 
}
 

	
 
/**
 
 * Sets the disallowed directions
 
 * @param t   the tile to set the directions for
 
 * @param drd the disallowed directions
 
 */
 
static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirections drd)
 
{
 
	assert(IsNormalRoad(t));
 
	assert(drd < DRD_END);
 
	SB(_m[t].m5, 4, 2, drd);
 
}
 

	
 
static inline Axis GetCrossingRoadAxis(TileIndex t)
 
{
 
	assert(IsLevelCrossing(t));
 
	return (Axis)GB(_m[t].m4, 6, 1);
 
}
 

	
 
static inline Axis GetCrossingRailAxis(TileIndex t)
 
{
 
	assert(IsLevelCrossing(t));
 
	return OtherAxis((Axis)GetCrossingRoadAxis(t));
 
}
 

	
 
static inline RoadBits GetCrossingRoadBits(TileIndex tile)
 
{
 
	return GetCrossingRoadAxis(tile) == AXIS_X ? ROAD_X : ROAD_Y;
src/smallmap_gui.cpp
Show inline comments
 
@@ -445,96 +445,100 @@ static inline uint32 GetSmallMapVegetati
 
	uint32 bits;
 

	
 
	switch (t) {
 
		case MP_CLEAR:
 
			if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) {
 
				bits = MKCOLOR(0x37373737);
 
			} else {
 
				bits = _vegetation_clear_bits[GetClearGround(tile)];
 
			}
 
			break;
 

	
 
		case MP_INDUSTRY:
 
			bits = GetIndustrySpec(GetIndustryByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOR(0xD0D0D0D0) : MKCOLOR(0xB5B5B5B5);
 
			break;
 

	
 
		case MP_TREES:
 
			if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) {
 
				bits = (_opt.landscape == LT_ARCTIC) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2);
 
			} else {
 
				bits = MKCOLOR(0x54575754);
 
			}
 
			break;
 

	
 
		default:
 
			bits = ApplyMask(MKCOLOR(0x54545454), &_smallmap_vehicles_andor[t]);
 
			break;
 
	}
 

	
 
	return bits;
 
}
 

	
 

	
 
static uint32 _owner_colors[OWNER_END + 1];
 

	
 
/**
 
 * Return the color a tile would be displayed with in the small map in mode "Owner".
 
 *
 
 * @param tile The tile of which we would like to get the color.
 
 * @return The color of tile in the small map in mode "Owner"
 
 */
 
static inline uint32 GetSmallMapOwnerPixels(TileIndex tile)
 
{
 
	Owner o;
 

	
 
	switch (GetTileType(tile)) {
 
		case MP_INDUSTRY: o = OWNER_END;          break;
 
		case MP_HOUSE:    o = OWNER_TOWN;         break;
 
		default:          o = GetTileOwner(tile); break;
 
		/* FIXME: For MP_ROAD there are multiple owners.
 
		 * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
 
		 * even if there are no ROADTYPE_ROAD bits on the tile.
 
		 */
 
	}
 

	
 
	return _owner_colors[o];
 
}
 

	
 

	
 
static const uint32 _smallmap_mask_left[3] = {
 
	MKCOLOR(0xFF000000),
 
	MKCOLOR(0xFFFF0000),
 
	MKCOLOR(0xFFFFFF00),
 
};
 

	
 
static const uint32 _smallmap_mask_right[] = {
 
	MKCOLOR(0x000000FF),
 
	MKCOLOR(0x0000FFFF),
 
	MKCOLOR(0x00FFFFFF),
 
};
 

	
 
/* each tile has 4 x pixels and 1 y pixel */
 

	
 
static GetSmallMapPixels *_smallmap_draw_procs[] = {
 
	GetSmallMapContoursPixels,
 
	GetSmallMapVehiclesPixels,
 
	GetSmallMapIndustriesPixels,
 
	GetSmallMapRoutesPixels,
 
	GetSmallMapVegetationPixels,
 
	GetSmallMapOwnerPixels,
 
};
 

	
 
static const byte _vehicle_type_colors[6] = {
 
	184, 191, 152, 15, 215, 184
 
};
 

	
 

	
 
static void DrawVertMapIndicator(int x, int y, int x2, int y2)
 
{
 
	GfxFillRect(x, y,      x2, y + 3, 69);
 
	GfxFillRect(x, y2 - 3, x2, y2,    69);
 
}
 

	
 
static void DrawHorizMapIndicator(int x, int y, int x2, int y2)
 
{
 
	GfxFillRect(x,      y, x + 3, y2, 69);
 
	GfxFillRect(x2 - 3, y, x2,    y2, 69);
 
}
 

	
 
enum SmallMapWindowWidgets {
 
	SM_WIDGET_MAP = 4,
src/station_cmd.cpp
Show inline comments
 
@@ -1255,123 +1255,126 @@ static CommandCost RemoveRailroadStation
 

	
 
		free(st->speclist);
 
		st->num_specs = 0;
 
		st->speclist  = NULL;
 
		st->cached_anim_triggers = 0;
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		UpdateStationVirtCoordDirty(st);
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**
 
 * @param truck_station Determines whether a stop is ROADSTOP_BUS or ROADSTOP_TRUCK
 
 * @param st The Station to do the whole procedure for
 
 * @return a pointer to where to link a new RoadStop*
 
 */
 
static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
 
{
 
	RoadStop **primary_stop = (truck_station) ? &st->truck_stops : &st->bus_stops;
 

	
 
	if (*primary_stop == NULL) {
 
		/* we have no roadstop of the type yet, so write a "primary stop" */
 
		return primary_stop;
 
	} else {
 
		/* there are stops already, so append to the end of the list */
 
		RoadStop *stop = *primary_stop;
 
		while (stop->next != NULL) stop = stop->next;
 
		return &stop->next;
 
	}
 
}
 

	
 
/** Build a bus or truck stop
 
 * @param tile tile to build the stop at
 
 * @param flags operation to perform
 
 * @param p1 entrance direction (DiagDirection)
 
 * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
 
 *           bit 1: 0 for normal, 1 for drive-through
 
 *           bit 2..4: the roadtypes
 
 *           bit 5: allow stations directly adjacent to other stations.
 
 */
 
CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	bool type = HasBit(p2, 0);
 
	bool is_drive_through = HasBit(p2, 1);
 
	bool build_over_road  = is_drive_through && IsNormalRoadTile(tile);
 
	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
 
	bool town_owned_road  = false;
 
	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
 

	
 
	if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
 

	
 
	/* Trams only have drive through stops */
 
	if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR;
 

	
 
	/* Saveguard the parameters */
 
	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
 
	/* If it is a drive-through stop check for valid axis */
 
	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
 
	/* Road bits in the wrong direction */
 
	if (build_over_road && (GetAllRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
 

	
 
	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
 

	
 
	/* Not allowed to build over this road */
 
	if (build_over_road) {
 
		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
 

	
 
		RoadTypes cur_rts = GetRoadTypes(tile);
 

	
 
		/* there is a road, check if we can build road+tram stop over it */
 
		if (HasBit(cur_rts, ROADTYPE_ROAD)) {
 
			Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
 
			if (road_owner != OWNER_TOWN && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR;
 
			if (road_owner == OWNER_TOWN) {
 
				town_owned_road = true;
 
				if (!_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
 
			} else {
 
				if (road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR;
 
			}
 
		}
 

	
 
		/* there is a tram, check if we can build road+tram stop over it */
 
		if (HasBit(cur_rts, ROADTYPE_TRAM)) {
 
			Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
 
			if (tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) return CMD_ERROR;
 
		}
 

	
 
		/* Don't allow building the roadstop when vehicles are already driving on it */
 
		if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 

	
 
		/* Do not remove roadtypes! */
 
		rts |= cur_rts;
 
	}
 

	
 
	CommandCost cost = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL, !build_over_road);
 
	if (CmdFailed(cost)) return cost;
 

	
 
	Station *st = NULL;
 

	
 
	if (!_patches.adjacent_stations || !HasBit(p2, 5)) {
 
		st = GetStationAround(tile, 1, 1, INVALID_STATION);
 
		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 
	}
 

	
 
	/* Find a station close to us */
 
	if (st == NULL) st = GetClosestStationFromTile(tile);
 

	
 
	/* give us a road stop in the list, and check if something went wrong */
 
	if (!RoadStop::CanAllocateItem()) return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 

	
 
	if (st != NULL &&
 
			GetNumRoadStopsInStation(st, ROADSTOP_BUS) + GetNumRoadStopsInStation(st, ROADSTOP_TRUCK) >= RoadStop::LIMIT) {
 
		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 
	}
 

	
 
	if (st != NULL) {
 
		if (st->owner != _current_player) {
 
			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
 
		}
 

	
 
		if (!st->rect.BeforeAddTile(tile, StationRect::ADD_TEST)) return CMD_ERROR;
 
	} else {
 
		/* allocate and initialize new station */
 
		if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 

	
 
		if (flags & DC_EXEC) {
 
			st = new Station(tile);
src/town_cmd.cpp
Show inline comments
 
@@ -1167,104 +1167,104 @@ static void GrowTownInTile(TileIndex *ti
 
 * @param t town to inquiry
 
 * @param tile to inquiry
 
 * @return something other than zero(0)if town expansion was possible
 
 */
 
static int GrowTownAtRoad(Town *t, TileIndex tile)
 
{
 
	/* Special case.
 
	 * @see GrowTownInTile Check the else if
 
	 */
 
	DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town
 

	
 
	TILE_ASSERT(tile);
 

	
 
	/* Number of times to search.
 
	 * Better roads, 2X2 and 3X3 grid grow quite fast so we give
 
	 * them a little handicap. */
 
	switch (t->GetActiveLayout()) {
 
		case TL_BETTER_ROADS:
 
			_grow_town_result = 10 + t->num_houses * 2 / 9;
 
			break;
 

	
 
		case TL_3X3_GRID:
 
		case TL_2X2_GRID:
 
			_grow_town_result = 10 + t->num_houses * 1 / 9;
 
			break;
 

	
 
		default:
 
			_grow_town_result = 10 + t->num_houses * 4 / 9;
 
			break;
 
	}
 

	
 
	do {
 
		RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile
 

	
 
		/* Try to grow the town from this point */
 
		GrowTownInTile(&tile, cur_rb, target_dir, t);
 

	
 
		/* Exclude the source position from the bitmask
 
		 * and return if no more road blocks available */
 
		cur_rb &= ~DiagDirToRoadBits(ReverseDiagDir(target_dir));
 
		if (cur_rb == ROAD_NONE)
 
			return _grow_town_result;
 

	
 
		/* Select a random bit from the blockmask, walk a step
 
		 * and continue the search from there. */
 
		do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir)));
 
		tile = TileAddByDiagDir(tile, target_dir);
 

	
 
		if (IsTileType(tile, MP_ROAD)) {
 
		if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, ROADTYPE_ROAD)) {
 
			/* Don't allow building over roads of other cities */
 
			if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) {
 
			if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) && GetTownByTile(tile) != t) {
 
				_grow_town_result = GROWTH_SUCCEED;
 
			} else if (IsTileOwner(tile, OWNER_NONE) && _game_mode == GM_EDITOR) {
 
			} else if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) {
 
				/* If we are in the SE, and this road-piece has no town owner yet, it just found an
 
				 * owner :) (happy happy happy road now) */
 
				SetTileOwner(tile, OWNER_TOWN);
 
				SetRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN);
 
				SetTownIndex(tile, t->index);
 
			}
 
		}
 

	
 
		/* Max number of times is checked. */
 
	} while (--_grow_town_result >= 0);
 

	
 
	return (_grow_town_result == -2);
 
}
 

	
 
/**
 
 * Generate a random road block.
 
 * The probability of a straight road
 
 * is somewhat higher than a curved.
 
 *
 
 * @return A RoadBits value with 2 bits set
 
 */
 
static RoadBits GenRandomRoadBits()
 
{
 
	uint32 r = Random();
 
	uint a = GB(r, 0, 2);
 
	uint b = GB(r, 8, 2);
 
	if (a == b) b ^= 2;
 
	return (RoadBits)((ROAD_NW << a) + (ROAD_NW << b));
 
}
 

	
 
/** Grow the town
 
 * @param t town to grow
 
 * @return true iff a house was built
 
 */
 
static bool GrowTown(Town *t)
 
{
 
	/* Let the town be a ghost town
 
	 * The player wanted it in such a way. Thus there he has it. ;)
 
	 * Never reached in editor mode. */
 
	if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
 
		return false;
 
	}
 

	
 
	static const TileIndexDiffC _town_coord_mod[] = {
 
		{-1,  0},
 
		{ 1,  1},
 
		{ 1, -1},
 
		{-1, -1},
 
		{-1,  0},
 
		{ 0,  2},
 
		{ 2,  0},
 
		{ 0, -2},
 
@@ -2393,98 +2393,98 @@ static void UpdateTownAmounts(Town *t)
 
}
 

	
 
static void UpdateTownUnwanted(Town *t)
 
{
 
	const Player *p;
 

	
 
	FOR_ALL_PLAYERS(p) {
 
		if (t->unwanted[p->index] > 0) t->unwanted[p->index]--;
 
	}
 
}
 

	
 
bool CheckIfAuthorityAllows(TileIndex tile)
 
{
 
	if (!IsValidPlayer(_current_player)) return true;
 

	
 
	Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
 
	if (t == NULL) return true;
 

	
 
	if (t->ratings[_current_player] > RATING_VERYPOOR) return true;
 

	
 
	_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
 
	SetDParam(0, t->index);
 

	
 
	return false;
 
}
 

	
 

	
 
Town *CalcClosestTownFromTile(TileIndex tile, uint threshold)
 
{
 
	Town *t;
 
	uint best = threshold;
 
	Town *best_town = NULL;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		uint dist = DistanceManhattan(tile, t->xy);
 
		if (dist < best) {
 
			best = dist;
 
			best_town = t;
 
		}
 
	}
 

	
 
	return best_town;
 
}
 

	
 

	
 
Town *ClosestTownFromTile(TileIndex tile, uint threshold)
 
{
 
	if (IsTileType(tile, MP_HOUSE) || (
 
				IsTileType(tile, MP_ROAD) &&
 
				GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN
 
				IsTileType(tile, MP_ROAD) && HasTileRoadType(tile, ROADTYPE_ROAD) &&
 
				IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)
 
			)) {
 
		return GetTownByTile(tile);
 
	} else {
 
		return CalcClosestTownFromTile(tile, threshold);
 
	}
 
}
 

	
 
static bool _town_rating_test = false;
 
std::map<const Town *, int> _town_test_ratings;
 

	
 
void SetTownRatingTestMode(bool mode)
 
{
 
	static int ref_count = 0;
 
	if (mode) {
 
		if (ref_count == 0) {
 
			_town_test_ratings.clear();
 
		}
 
		ref_count++;
 
	} else {
 
		assert(ref_count > 0);
 
		ref_count--;
 
	}
 
	_town_rating_test = !(ref_count == 0);
 
}
 

	
 
static int GetRating(const Town *t)
 
{
 
	if (_town_rating_test) {
 
		std::map<const Town *, int>::iterator it = _town_test_ratings.find(t);
 
		if (it != _town_test_ratings.end()) {
 
			return (*it).second;
 
		}
 
	}
 
	return t->ratings[_current_player];
 
}
 

	
 
void ChangeTownRating(Town *t, int add, int max)
 
{
 
	/* if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff */
 
	if (t == NULL ||
 
			!IsValidPlayer(_current_player) ||
 
			(_cheats.magic_bulldozer.value && add < 0)) {
 
		return;
 
	}
 

	
 
	SetBit(t->have_ratings, _current_player);
 

	
 
	int rating = GetRating(t);
0 comments (0 inline, 0 general)