src/water_cmd.cpp
branchnoai
changeset 9724 b39bc69bb2f2
parent 9723 eee46cb39750
child 9732 f8eb3e208514
equal deleted inserted replaced
9723:eee46cb39750 9724:b39bc69bb2f2
     6 #include "openttd.h"
     6 #include "openttd.h"
     7 #include "bridge_map.h"
     7 #include "bridge_map.h"
     8 #include "bridge.h"
     8 #include "bridge.h"
     9 #include "cmd_helper.h"
     9 #include "cmd_helper.h"
    10 #include "station_map.h"
    10 #include "station_map.h"
    11 #include "table/sprites.h"
       
    12 #include "table/strings.h"
       
    13 #include "tile_cmd.h"
    11 #include "tile_cmd.h"
    14 #include "landscape.h"
    12 #include "landscape.h"
    15 #include "viewport_func.h"
    13 #include "viewport_func.h"
    16 #include "command_func.h"
    14 #include "command_func.h"
    17 #include "town.h"
    15 #include "town.h"
    31 #include "functions.h"
    29 #include "functions.h"
    32 #include "window_func.h"
    30 #include "window_func.h"
    33 #include "vehicle_func.h"
    31 #include "vehicle_func.h"
    34 #include "sound_func.h"
    32 #include "sound_func.h"
    35 #include "variables.h"
    33 #include "variables.h"
    36 
    34 #include "player_func.h"
    37 
    35 #include "settings_type.h"
    38 static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
    36 #include "clear_map.h"
    39 static void FloodVehicle(Vehicle *v);
    37 #include "tree_map.h"
       
    38 
       
    39 #include "table/sprites.h"
       
    40 #include "table/strings.h"
       
    41 
       
    42 /**
       
    43  * Describes the behaviour of a tile during flooding.
       
    44  */
       
    45 enum FloodingBehaviour {
       
    46 	FLOOD_NONE,    ///< The tile does not flood neighboured tiles.
       
    47 	FLOOD_ACTIVE,  ///< The tile floods neighboured tiles.
       
    48 	FLOOD_PASSIVE, ///< The tile does not actively flood neighboured tiles, but it prevents them from drying up.
       
    49 	FLOOD_DRYUP,   ///< The tile drys up if it is not constantly flooded from neighboured tiles.
       
    50 };
       
    51 
       
    52 /**
       
    53  * Describes from which directions a specific slope can be flooded (if the tile is floodable at all).
       
    54  */
       
    55 static const uint8 _flood_from_dirs[] = {
       
    56 	(1 << DIR_NW) | (1 << DIR_SW) | (1 << DIR_SE) | (1 << DIR_NE), // SLOPE_FLAT
       
    57 	(1 << DIR_NE) | (1 << DIR_SE),                                 // SLOPE_W
       
    58 	(1 << DIR_NW) | (1 << DIR_NE),                                 // SLOPE_S
       
    59 	(1 << DIR_NE),                                                 // SLOPE_SW
       
    60 	(1 << DIR_NW) | (1 << DIR_SW),                                 // SLOPE_E
       
    61 	0,                                                             // SLOPE_EW
       
    62 	(1 << DIR_NW),                                                 // SLOPE_SE
       
    63 	(1 << DIR_N ) | (1 << DIR_NW) | (1 << DIR_NE),                 // SLOPE_WSE, SLOPE_STEEP_S
       
    64 	(1 << DIR_SW) | (1 << DIR_SE),                                 // SLOPE_N
       
    65 	(1 << DIR_SE),                                                 // SLOPE_NW
       
    66 	0,                                                             // SLOPE_NS
       
    67 	(1 << DIR_E ) | (1 << DIR_NE) | (1 << DIR_SE),                 // SLOPE_NWS, SLOPE_STEEP_W
       
    68 	(1 << DIR_SW),                                                 // SLOPE_NE
       
    69 	(1 << DIR_S ) | (1 << DIR_SW) | (1 << DIR_SE),                 // SLOPE_ENW, SLOPE_STEEP_N
       
    70 	(1 << DIR_W ) | (1 << DIR_SW) | (1 << DIR_NW),                 // SLOPE_SEN, SLOPE_STEEP_E
       
    71 };
       
    72 
       
    73 /**
       
    74  * Marks tile dirty if it is a canal or river tile.
       
    75  * Called to avoid glitches when flooding tiles next to canal tile.
       
    76  *
       
    77  * @param tile tile to check
       
    78  */
       
    79 static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
       
    80 {
       
    81 	if (IsTileType(tile, MP_WATER) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
       
    82 }
       
    83 
       
    84 /**
       
    85  * Marks the tiles around a tile as dirty, if they are canals or rivers.
       
    86  *
       
    87  * @param tile The center of the tile where all other tiles are marked as dirty
       
    88  * @ingroup dirty
       
    89  */
       
    90 static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
       
    91 {
       
    92 	for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
       
    93 		MarkTileDirtyIfCanalOrRiver(tile + TileOffsByDir(dir));
       
    94 	}
       
    95 }
    40 
    96 
    41 /**
    97 /**
    42  * Makes a tile canal or water depending on the surroundings.
    98  * Makes a tile canal or water depending on the surroundings.
    43  * This as for example docks and shipdepots do not store
    99  * This as for example docks and shipdepots do not store
    44  * whether the tile used to be canal or 'normal' water.
   100  * whether the tile used to be canal or 'normal' water.
    45  * @param t the tile to change.
   101  * @param t the tile to change.
    46  * @param o the owner of the new tile.
   102  * @param o the owner of the new tile.
    47  */
   103  */
    48 void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o)
   104 void SetWaterClassDependingOnSurroundings(TileIndex t)
    49 {
   105 {
    50 	assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
   106 	assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
    51 
   107 
    52 	/* Mark tile dirty in all cases */
   108 	/* Mark tile dirty in all cases */
    53 	MarkTileDirtyByTile(t);
   109 	MarkTileDirtyByTile(t);
    54 
   110 
    55 	/* Non-sealevel -> canal */
       
    56 	if (TileHeight(t) != 0) {
       
    57 		MakeCanal(t, o);
       
    58 		return;
       
    59 	}
       
    60 
       
    61 	bool has_water = false;
   111 	bool has_water = false;
    62 	bool has_canal = false;
   112 	bool has_canal = false;
       
   113 	bool has_river = false;
    63 
   114 
    64 	for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
   115 	for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
    65 		TileIndex neighbour = TileAddByDiagDir(t, dir);
   116 		TileIndex neighbour = TileAddByDiagDir(t, dir);
    66 		if (IsTileType(neighbour, MP_WATER)) {
   117 		switch (GetTileType(neighbour)) {
    67 			has_water |= IsSea(neighbour) || IsCoast(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) == OWNER_WATER);
   118 			case MP_WATER:
    68 			has_canal |= IsCanal(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) != OWNER_WATER);
   119 				has_water |= IsSea(neighbour) || IsCoast(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) == OWNER_WATER);
       
   120 				has_canal |= IsCanal(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) != OWNER_WATER);
       
   121 				has_river |= IsRiver(neighbour);
       
   122 				break;
       
   123 
       
   124 			case MP_RAILWAY:
       
   125 				/* Shore or flooded halftile */
       
   126 				has_water |= (GetRailGroundType(neighbour) == RAIL_GROUND_WATER);
       
   127 				break;
       
   128 
       
   129 			case MP_TREES:
       
   130 				/* trees on shore */
       
   131 				has_water |= (GetTreeGround(neighbour) == TREE_GROUND_SHORE);
       
   132 				break;
       
   133 
       
   134 			default: break;
    69 		}
   135 		}
    70 	}
   136 	}
    71 	if (has_canal || !has_water) {
   137 
    72 		MakeCanal(t, o);
   138 	if (has_river && !has_canal) {
       
   139 		SetWaterClass(t, WATER_CLASS_RIVER);
       
   140 	} else if (has_canal || !has_water) {
       
   141 		SetWaterClass(t, WATER_CLASS_CANAL);
    73 	} else {
   142 	} else {
    74 		MakeWater(t);
   143 		SetWaterClass(t, WATER_CLASS_SEA);
    75 	}
   144 	}
    76 }
   145 }
    77 
   146 
    78 
   147 
    79 /** Build a ship depot.
   148 /** Build a ship depot.
    90 
   159 
    91 	Axis axis = Extract<Axis, 0>(p1);
   160 	Axis axis = Extract<Axis, 0>(p1);
    92 
   161 
    93 	tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
   162 	tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
    94 
   163 
    95 	if (!IsWaterTile(tile) || !IsWaterTile(tile2))
   164 	if (!IsWaterTile(tile) || !IsWaterTile(tile2)) {
    96 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
   165 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
       
   166 	}
    97 
   167 
    98 	if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   168 	if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
    99 
   169 
       
   170 	if (GetTileSlope(tile, NULL) != SLOPE_FLAT || GetTileSlope(tile2, NULL) != SLOPE_FLAT) {
       
   171 		/* Prevent depots on rapids */
       
   172 		return_cmd_error(STR_0239_SITE_UNSUITABLE);
       
   173 	}
       
   174 
       
   175 	WaterClass wc1 = GetWaterClass(tile);
       
   176 	WaterClass wc2 = GetWaterClass(tile2);
   100 	Owner o1 = GetTileOwner(tile);
   177 	Owner o1 = GetTileOwner(tile);
   101 	Owner o2 = GetTileOwner(tile2);
   178 	Owner o2 = GetTileOwner(tile2);
   102 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   179 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   103 	if (CmdFailed(ret)) return CMD_ERROR;
   180 	if (CmdFailed(ret)) return CMD_ERROR;
   104 	ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   181 	ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   109 	AutoPtrT<Depot> d_auto_delete = depot;
   186 	AutoPtrT<Depot> d_auto_delete = depot;
   110 
   187 
   111 	if (flags & DC_EXEC) {
   188 	if (flags & DC_EXEC) {
   112 		depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   189 		depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   113 
   190 
   114 		MakeShipDepot(tile,  _current_player, DEPOT_NORTH, axis, o1);
   191 		MakeShipDepot(tile,  _current_player, DEPOT_NORTH, axis, wc1, o1);
   115 		MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, o2);
   192 		MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, wc2, o2);
   116 		MarkTileDirtyByTile(tile);
   193 		MarkTileDirtyByTile(tile);
   117 		MarkTileDirtyByTile(tile2);
   194 		MarkTileDirtyByTile(tile2);
   118 		d_auto_delete.Detach();
   195 		d_auto_delete.Detach();
   119 	}
   196 	}
   120 
   197 
   121 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot);
   198 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot);
   122 }
   199 }
   123 
   200 
   124 void MakeWaterOrCanalDependingOnOwner(TileIndex tile, Owner o)
   201 void MakeWaterKeepingClass(TileIndex tile, Owner o)
   125 {
   202 {
   126 	if (o == OWNER_WATER) {
   203 	assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile))));
   127 		MakeWater(tile);
   204 
   128 	} else {
   205 	switch (GetWaterClass(tile)) {
   129 		MakeCanal(tile, o);
   206 		case WATER_CLASS_SEA:   MakeWater(tile);              break;
       
   207 		case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
       
   208 		case WATER_CLASS_RIVER: MakeRiver(tile, Random());    break;
   130 	}
   209 	}
   131 }
   210 }
   132 
   211 
   133 static CommandCost RemoveShipDepot(TileIndex tile, uint32 flags)
   212 static CommandCost RemoveShipDepot(TileIndex tile, uint32 flags)
   134 {
   213 {
   144 
   223 
   145 	if (flags & DC_EXEC) {
   224 	if (flags & DC_EXEC) {
   146 		/* Kill the depot, which is registered at the northernmost tile. Use that one */
   225 		/* Kill the depot, which is registered at the northernmost tile. Use that one */
   147 		delete GetDepotByTile(tile2 < tile ? tile2 : tile);
   226 		delete GetDepotByTile(tile2 < tile ? tile2 : tile);
   148 
   227 
   149 		MakeWaterOrCanalDependingOnOwner(tile,  GetShipDepotWaterOwner(tile));
   228 		MakeWaterKeepingClass(tile,  GetShipDepotWaterOwner(tile));
   150 		MakeWaterOrCanalDependingOnOwner(tile2, GetShipDepotWaterOwner(tile2));
   229 		MakeWaterKeepingClass(tile2, GetShipDepotWaterOwner(tile2));
   151 		MarkTileDirtyByTile(tile);
   230 		MarkTileDirtyByTile(tile);
   152 		MarkTileDirtyByTile(tile2);
   231 		MarkTileDirtyByTile(tile2);
   153 	}
   232 	}
   154 
   233 
   155 	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_ship_depot);
   234 	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_ship_depot);
   165 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   244 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   166 	if (CmdFailed(ret)) return CMD_ERROR;
   245 	if (CmdFailed(ret)) return CMD_ERROR;
   167 
   246 
   168 	delta = TileOffsByDiagDir(dir);
   247 	delta = TileOffsByDiagDir(dir);
   169 	/* lower tile */
   248 	/* lower tile */
       
   249 	WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
       
   250 
   170 	ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   251 	ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   171 	if (CmdFailed(ret)) return CMD_ERROR;
   252 	if (CmdFailed(ret)) return CMD_ERROR;
   172 	if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
   253 	if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
   173 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   254 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   174 	}
   255 	}
   175 
   256 
   176 	/* upper tile */
   257 	/* upper tile */
       
   258 	WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
       
   259 
   177 	ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   260 	ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   178 	if (CmdFailed(ret)) return CMD_ERROR;
   261 	if (CmdFailed(ret)) return CMD_ERROR;
   179 	if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
   262 	if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
   180 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   263 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   181 	}
   264 	}
   185 	    (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
   268 	    (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
   186 		return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   269 		return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   187 	}
   270 	}
   188 
   271 
   189 	if (flags & DC_EXEC) {
   272 	if (flags & DC_EXEC) {
   190 		MakeLock(tile, _current_player, dir);
   273 		MakeLock(tile, _current_player, dir, wc_lower, wc_upper);
   191 		MarkTileDirtyByTile(tile);
   274 		MarkTileDirtyByTile(tile);
   192 		MarkTileDirtyByTile(tile - delta);
   275 		MarkTileDirtyByTile(tile - delta);
   193 		MarkTileDirtyByTile(tile + delta);
   276 		MarkTileDirtyByTile(tile + delta);
       
   277 		MarkCanalsAndRiversAroundDirty(tile - delta);
       
   278 		MarkCanalsAndRiversAroundDirty(tile + delta);
   194 	}
   279 	}
   195 
   280 
   196 	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 22 >> 3);
   281 	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 22 >> 3);
   197 }
   282 }
   198 
   283 
   206 	if (!EnsureNoVehicleOnGround(tile) || !EnsureNoVehicleOnGround(tile + delta) || !EnsureNoVehicleOnGround(tile - delta))
   291 	if (!EnsureNoVehicleOnGround(tile) || !EnsureNoVehicleOnGround(tile + delta) || !EnsureNoVehicleOnGround(tile - delta))
   207 		return CMD_ERROR;
   292 		return CMD_ERROR;
   208 
   293 
   209 	if (flags & DC_EXEC) {
   294 	if (flags & DC_EXEC) {
   210 		DoClearSquare(tile);
   295 		DoClearSquare(tile);
   211 		MakeWaterOrCanalDependingOnSurroundings(tile + delta, _current_player);
   296 		MakeWaterKeepingClass(tile + delta, GetTileOwner(tile));
   212 		MakeWaterOrCanalDependingOnSurroundings(tile - delta, _current_player);
   297 		MakeWaterKeepingClass(tile - delta, GetTileOwner(tile));
       
   298 		MarkTileDirtyByTile(tile - delta);
       
   299 		MarkTileDirtyByTile(tile + delta);
       
   300 		MarkCanalsAndRiversAroundDirty(tile - delta);
       
   301 		MarkCanalsAndRiversAroundDirty(tile + delta);
   213 	}
   302 	}
   214 
   303 
   215 	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 2);
   304 	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 2);
   216 }
       
   217 
       
   218 /**
       
   219  * Marks the tiles around a tile as dirty.
       
   220  *
       
   221  * This functions marks the tiles around a given tile as dirty for repaint.
       
   222  *
       
   223  * @param tile The center of the tile where all other tiles are marked as dirty
       
   224  * @ingroup dirty
       
   225  * @see TerraformAddDirtyTileAround
       
   226  */
       
   227 static void MarkTilesAroundDirty(TileIndex tile)
       
   228 {
       
   229 	MarkTileDirtyByTile(TILE_ADDXY(tile, 0, 1));
       
   230 	MarkTileDirtyByTile(TILE_ADDXY(tile, 0, -1));
       
   231 	MarkTileDirtyByTile(TILE_ADDXY(tile, 1, 0));
       
   232 	MarkTileDirtyByTile(TILE_ADDXY(tile, -1, 0));
       
   233 }
   305 }
   234 
   306 
   235 /** Builds a lock (ship-lift)
   307 /** Builds a lock (ship-lift)
   236  * @param tile tile where to place the lock
   308  * @param tile tile where to place the lock
   237  * @param flags type of operation
   309  * @param flags type of operation
   238  * @param p1 unused
   310  * @param p1 unused
   239  * @param p2 unused
   311  * @param p2 unused
   240  */
   312  */
   241 CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   313 CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   242 {
   314 {
   243 	DiagDirection dir;
   315 	DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
   244 
   316 	if (dir == INVALID_DIAGDIR) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   245 	switch (GetTileSlope(tile, NULL)) {
   317 
   246 		case SLOPE_SW: dir = DIAGDIR_SW; break;
   318 	/* Disallow building of locks on river rapids */
   247 		case SLOPE_SE: dir = DIAGDIR_SE; break;
   319 	if (IsWaterTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE);
   248 		case SLOPE_NW: dir = DIAGDIR_NW; break;
   320 
   249 		case SLOPE_NE: dir = DIAGDIR_NE; break;
       
   250 		default: return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   251 	}
       
   252 	return DoBuildShiplift(tile, dir, flags);
   321 	return DoBuildShiplift(tile, dir, flags);
   253 }
   322 }
   254 
   323 
   255 /** Build a piece of canal.
   324 /** Build a piece of canal.
   256  * @param tile end tile of stretch-dragging
   325  * @param tile end tile of stretch-dragging
   257  * @param flags type of operation
   326  * @param flags type of operation
   258  * @param p1 start tile of stretch-dragging
   327  * @param p1 start tile of stretch-dragging
   259  * @param p2 ctrl pressed - toggles ocean / canals at sealevel (ocean only allowed in the scenario editor)
   328  * @param p2 specifies canal (0), water (1) or river (2); last two can only be built in scenario editor
   260  */
   329  */
   261 CommandCost CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   330 CommandCost CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   262 {
   331 {
   263 	CommandCost cost(EXPENSES_CONSTRUCTION);
   332 	CommandCost cost(EXPENSES_CONSTRUCTION);
   264 	int size_x, size_y;
   333 	int size_x, size_y;
   265 	int x;
   334 	int x;
   266 	int y;
   335 	int y;
   267 	int sx, sy;
   336 	int sx, sy;
   268 
   337 
   269 	if (p1 >= MapSize()) return CMD_ERROR;
   338 	if (p1 >= MapSize()) return CMD_ERROR;
       
   339 
   270 	/* Outside of the editor you can only build canals, not oceans */
   340 	/* Outside of the editor you can only build canals, not oceans */
   271 	if (HasBit(p2, 0) && _game_mode != GM_EDITOR) return CMD_ERROR;
   341 	if (p2 != 0 && _game_mode != GM_EDITOR) return CMD_ERROR;
   272 
   342 
   273 	x = TileX(tile);
   343 	x = TileX(tile);
   274 	y = TileY(tile);
   344 	y = TileY(tile);
   275 	sx = TileX(p1);
   345 	sx = TileX(p1);
   276 	sy = TileY(p1);
   346 	sy = TileY(p1);
   284 	if (_game_mode != GM_EDITOR && (sx != x && sy != y)) return CMD_ERROR;
   354 	if (_game_mode != GM_EDITOR && (sx != x && sy != y)) return CMD_ERROR;
   285 
   355 
   286 	BEGIN_TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
   356 	BEGIN_TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
   287 		CommandCost ret;
   357 		CommandCost ret;
   288 
   358 
   289 		if (GetTileSlope(tile, NULL) != SLOPE_FLAT) {
   359 		Slope slope = GetTileSlope(tile, NULL);
       
   360 		if (slope != SLOPE_FLAT && (p2 != 2 || !IsInclinedSlope(slope))) {
   290 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   361 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   291 		}
   362 		}
   292 
   363 
   293 		/* can't make water of water! */
   364 		/* can't make water of water! */
   294 		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || HasBit(p2, 0))) continue;
   365 		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || p2 == 1)) continue;
   295 
   366 
   296 		ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   367 		ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   297 		if (CmdFailed(ret)) return ret;
   368 		if (CmdFailed(ret)) return ret;
   298 		cost.AddCost(ret);
   369 		cost.AddCost(ret);
   299 
   370 
   300 		if (flags & DC_EXEC) {
   371 		if (flags & DC_EXEC) {
   301 			if (TileHeight(tile) == 0 && HasBit(p2, 0)) {
   372 			if (TileHeight(tile) == 0 && p2 == 1) {
   302 				MakeWater(tile);
   373 				MakeWater(tile);
       
   374 			} else if (p2 == 2) {
       
   375 				MakeRiver(tile, Random());
   303 			} else {
   376 			} else {
   304 				MakeCanal(tile, _current_player);
   377 				MakeCanal(tile, _current_player, Random());
   305 			}
   378 			}
   306 			MarkTileDirtyByTile(tile);
   379 			MarkTileDirtyByTile(tile);
   307 			MarkTilesAroundDirty(tile);
   380 			MarkCanalsAndRiversAroundDirty(tile);
   308 		}
   381 		}
   309 
   382 
   310 		cost.AddCost(_price.clear_water);
   383 		cost.AddCost(_price.clear_water);
   311 	} END_TILE_LOOP(tile, size_x, size_y, 0);
   384 	} END_TILE_LOOP(tile, size_x, size_y, 0);
   312 
   385 
   332 			/* Make sure no vehicle is on the tile */
   405 			/* Make sure no vehicle is on the tile */
   333 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   406 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   334 
   407 
   335 			if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR;
   408 			if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR;
   336 
   409 
   337 			if (flags & DC_EXEC) DoClearSquare(tile);
   410 			if (flags & DC_EXEC) {
       
   411 				DoClearSquare(tile);
       
   412 				MarkCanalsAndRiversAroundDirty(tile);
       
   413 			}
   338 			return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
   414 			return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
   339 
   415 
   340 		case WATER_TILE_COAST: {
   416 		case WATER_TILE_COAST: {
   341 			Slope slope = GetTileSlope(tile, NULL);
   417 			Slope slope = GetTileSlope(tile, NULL);
   342 
   418 
   343 			/* Make sure no vehicle is on the tile */
   419 			/* Make sure no vehicle is on the tile */
   344 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   420 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   345 
   421 
   346 			if (flags & DC_EXEC) DoClearSquare(tile);
   422 			if (flags & DC_EXEC) {
   347 			if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) {
   423 				DoClearSquare(tile);
       
   424 				MarkCanalsAndRiversAroundDirty(tile);
       
   425 			}
       
   426 			if (IsSlopeWithOneCornerRaised(slope)) {
   348 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
   427 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
   349 			} else {
   428 			} else {
   350 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_roughland);
   429 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_roughland);
   351 			}
   430 			}
   352 		}
   431 		}
   371 		default:
   450 		default:
   372 			NOT_REACHED();
   451 			NOT_REACHED();
   373 	}
   452 	}
   374 }
   453 }
   375 
   454 
   376 /** return true if a tile is a water tile. */
   455 /**
   377 static bool IsWateredTile(TileIndex tile)
   456  * return true if a tile is a water tile wrt. a certain direction.
       
   457  *
       
   458  * @param tile The tile of interest.
       
   459  * @param from The direction of interest.
       
   460  * @return true iff the tile is water in the view of 'from'.
       
   461  *
       
   462  */
       
   463 static bool IsWateredTile(TileIndex tile, Direction from)
   378 {
   464 {
   379 	switch (GetTileType(tile)) {
   465 	switch (GetTileType(tile)) {
   380 		case MP_WATER:
   466 		case MP_WATER:
   381 			if (!IsCoast(tile)) return true;
   467 			if (!IsCoast(tile)) return true;
   382 
       
   383 			switch (GetTileSlope(tile, NULL)) {
   468 			switch (GetTileSlope(tile, NULL)) {
   384 				case SLOPE_W:
   469 				case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
   385 				case SLOPE_S:
   470 				case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
   386 				case SLOPE_E:
   471 				case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
   387 				case SLOPE_N:
   472 				case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
   388 					return true;
   473 				default: return false;
   389 
   474 			}
   390 				default:
   475 
   391 					return false;
   476 		case MP_RAILWAY:
   392 			}
   477 			if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
   393 
   478 				assert(IsPlainRailTile(tile));
   394 		case MP_STATION:  return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile);
   479 				switch (GetTileSlope(tile, NULL)) {
       
   480 					case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
       
   481 					case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
       
   482 					case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
       
   483 					case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
       
   484 					default: return false;
       
   485 				}
       
   486 			}
       
   487 			return false;
       
   488 
       
   489 		case MP_STATION:  return IsOilRig(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
   395 		case MP_INDUSTRY: return (GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
   490 		case MP_INDUSTRY: return (GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
   396 		default:          return false;
   491 		default:          return false;
   397 	}
   492 	}
   398 }
   493 }
   399 
   494 
       
   495 static void DrawWaterEdges(SpriteID base, TileIndex tile)
       
   496 {
       
   497 	uint wa;
       
   498 
       
   499 	/* determine the edges around with water. */
       
   500 	wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0), DIR_SW) << 0;
       
   501 	wa += IsWateredTile(TILE_ADDXY(tile,  0,  1), DIR_NW) << 1;
       
   502 	wa += IsWateredTile(TILE_ADDXY(tile,  1,  0), DIR_NE) << 2;
       
   503 	wa += IsWateredTile(TILE_ADDXY(tile,  0, -1), DIR_SE) << 3;
       
   504 
       
   505 	if (!(wa & 1)) DrawGroundSprite(base,     PAL_NONE);
       
   506 	if (!(wa & 2)) DrawGroundSprite(base + 1, PAL_NONE);
       
   507 	if (!(wa & 4)) DrawGroundSprite(base + 2, PAL_NONE);
       
   508 	if (!(wa & 8)) DrawGroundSprite(base + 3, PAL_NONE);
       
   509 
       
   510 	/* right corner */
       
   511 	switch (wa & 0x03) {
       
   512 		case 0: DrawGroundSprite(base + 4, PAL_NONE); break;
       
   513 		case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawGroundSprite(base + 8, PAL_NONE); break;
       
   514 	}
       
   515 
       
   516 	/* bottom corner */
       
   517 	switch (wa & 0x06) {
       
   518 		case 0: DrawGroundSprite(base + 5, PAL_NONE); break;
       
   519 		case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawGroundSprite(base + 9, PAL_NONE); break;
       
   520 	}
       
   521 
       
   522 	/* left corner */
       
   523 	switch (wa & 0x0C) {
       
   524 		case  0: DrawGroundSprite(base + 6, PAL_NONE); break;
       
   525 		case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawGroundSprite(base + 10, PAL_NONE); break;
       
   526 	}
       
   527 
       
   528 	/* upper corner */
       
   529 	switch (wa & 0x09) {
       
   530 		case 0: DrawGroundSprite(base + 7, PAL_NONE); break;
       
   531 		case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawGroundSprite(base + 11, PAL_NONE); break;
       
   532 	}
       
   533 }
       
   534 
       
   535 /** Draw a plain sea water tile with no edges */
       
   536 void DrawSeaWater(TileIndex tile)
       
   537 {
       
   538 	DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
       
   539 }
       
   540 
   400 /** draw a canal styled water tile with dikes around */
   541 /** draw a canal styled water tile with dikes around */
   401 void DrawCanalWater(TileIndex tile)
   542 void DrawCanalWater(TileIndex tile, bool draw_base)
   402 {
   543 {
   403 	uint wa;
   544 	if (draw_base) DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
   404 
   545 
   405 	/* Test for custom graphics, else use the default */
   546 	/* Test for custom graphics, else use the default */
   406 	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
   547 	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
   407 	if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
   548 	if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
   408 
   549 
   409 	/* determine the edges around with water. */
   550 	DrawWaterEdges(dikes_base, tile);
   410 	wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0)) << 0;
       
   411 	wa += IsWateredTile(TILE_ADDXY(tile,  0,  1)) << 1;
       
   412 	wa += IsWateredTile(TILE_ADDXY(tile,  1,  0)) << 2;
       
   413 	wa += IsWateredTile(TILE_ADDXY(tile,  0, -1)) << 3;
       
   414 
       
   415 	if (!(wa & 1)) DrawGroundSprite(dikes_base,     PAL_NONE);
       
   416 	if (!(wa & 2)) DrawGroundSprite(dikes_base + 1, PAL_NONE);
       
   417 	if (!(wa & 4)) DrawGroundSprite(dikes_base + 2, PAL_NONE);
       
   418 	if (!(wa & 8)) DrawGroundSprite(dikes_base + 3, PAL_NONE);
       
   419 
       
   420 	/* right corner */
       
   421 	switch (wa & 0x03) {
       
   422 		case 0: DrawGroundSprite(dikes_base + 4, PAL_NONE); break;
       
   423 		case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(dikes_base + 8, PAL_NONE); break;
       
   424 	}
       
   425 
       
   426 	/* bottom corner */
       
   427 	switch (wa & 0x06) {
       
   428 		case 0: DrawGroundSprite(dikes_base + 5, PAL_NONE); break;
       
   429 		case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(dikes_base + 9, PAL_NONE); break;
       
   430 	}
       
   431 
       
   432 	/* left corner */
       
   433 	switch (wa & 0x0C) {
       
   434 		case  0: DrawGroundSprite(dikes_base + 6, PAL_NONE); break;
       
   435 		case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(dikes_base + 10, PAL_NONE); break;
       
   436 	}
       
   437 
       
   438 	/* upper corner */
       
   439 	switch (wa & 0x09) {
       
   440 		case 0: DrawGroundSprite(dikes_base + 7, PAL_NONE); break;
       
   441 		case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(dikes_base + 11, PAL_NONE); break;
       
   442 	}
       
   443 }
   551 }
   444 
   552 
   445 struct LocksDrawTileStruct {
   553 struct LocksDrawTileStruct {
   446 	int8 delta_x, delta_y, delta_z;
   554 	int8 delta_x, delta_y, delta_z;
   447 	byte width, height, depth;
   555 	byte width, height, depth;
   478 			wdts->unk, ti->z + wdts->delta_z,
   586 			wdts->unk, ti->z + wdts->delta_z,
   479 			IsTransparencySet(TO_BUILDINGS));
   587 			IsTransparencySet(TO_BUILDINGS));
   480 	}
   588 	}
   481 }
   589 }
   482 
   590 
       
   591 void DrawRiverWater(const TileInfo *ti, bool draw_base)
       
   592 {
       
   593 	SpriteID image = SPR_FLAT_WATER_TILE;
       
   594 	SpriteID edges_base = GetCanalSprite(CF_RIVER_EDGE, ti->tile);
       
   595 
       
   596 	if (ti->tileh != SLOPE_FLAT) {
       
   597 		image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
       
   598 		if (image == 0) {
       
   599 			switch (ti->tileh) {
       
   600 				case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
       
   601 				case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP;   break;
       
   602 				case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP;   break;
       
   603 				case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
       
   604 				default:       image = SPR_FLAT_WATER_TILE;    break;
       
   605 			}
       
   606 		} else {
       
   607 			switch (ti->tileh) {
       
   608 				default: NOT_REACHED();
       
   609 				case SLOPE_SE:             edges_base += 12; break;
       
   610 				case SLOPE_NE: image += 1; edges_base += 24; break;
       
   611 				case SLOPE_SW: image += 2; edges_base += 36; break;
       
   612 				case SLOPE_NW: image += 3; edges_base += 48; break;
       
   613 			}
       
   614 		}
       
   615 	}
       
   616 
       
   617 	if (draw_base) DrawGroundSprite(image, PAL_NONE);
       
   618 
       
   619 	/* Draw river edges if available. */
       
   620 	if (edges_base > 48) DrawWaterEdges(edges_base, ti->tile);
       
   621 }
       
   622 
       
   623 void DrawShoreTile(Slope tileh)
       
   624 {
       
   625 	/* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
       
   626 	 * This allows to calculate the proper sprite to display for this Slope */
       
   627 	static const byte tileh_to_shoresprite[32] = {
       
   628 		0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
       
   629 		0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0,  5,  0, 10, 15, 0,
       
   630 	};
       
   631 
       
   632 	assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
       
   633 	assert(tileh != SLOPE_FLAT);     // Shore is never flat
       
   634 
       
   635 	assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS)); // No suitable sprites for current flooding behaviour
       
   636 
       
   637 	DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
       
   638 }
       
   639 
   483 static void DrawTile_Water(TileInfo *ti)
   640 static void DrawTile_Water(TileInfo *ti)
   484 {
   641 {
   485 	switch (GetWaterTileType(ti->tile)) {
   642 	switch (GetWaterTileType(ti->tile)) {
   486 		case WATER_TILE_CLEAR:
   643 		case WATER_TILE_CLEAR:
   487 			DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
   644 			switch (GetWaterClass(ti->tile)) {
   488 			if (IsCanal(ti->tile)) DrawCanalWater(ti->tile);
   645 				case WATER_CLASS_SEA:   DrawSeaWater(ti->tile); break;
       
   646 				case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, true); break;
       
   647 				case WATER_CLASS_RIVER: DrawRiverWater(ti, true); break;
       
   648 			}
   489 			DrawBridgeMiddle(ti);
   649 			DrawBridgeMiddle(ti);
   490 			break;
   650 			break;
   491 
   651 
   492 		case WATER_TILE_COAST: {
   652 		case WATER_TILE_COAST: {
   493 			/* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
   653 			DrawShoreTile(ti->tileh);
   494 			 * This allows to calculate the proper sprite to display for this Slope */
       
   495 			static const byte tileh_to_shoresprite[32] = {
       
   496 				0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
       
   497 				0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0,  5,  0, 10, 15, 0,
       
   498 			};
       
   499 
       
   500 			assert(!IsSteepSlope(ti->tileh));
       
   501 			DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[ti->tileh], PAL_NONE);
       
   502 			DrawBridgeMiddle(ti);
   654 			DrawBridgeMiddle(ti);
   503 		} break;
   655 		} break;
   504 
   656 
   505 		case WATER_TILE_LOCK: {
   657 		case WATER_TILE_LOCK: {
   506 			const WaterDrawTileStruct *t = _shiplift_display_seq[GetSection(ti->tile)];
   658 			const WaterDrawTileStruct *t = _shiplift_display_seq[GetSection(ti->tile)];
   566 static void AnimateTile_Water(TileIndex tile)
   718 static void AnimateTile_Water(TileIndex tile)
   567 {
   719 {
   568 	/* not used */
   720 	/* not used */
   569 }
   721 }
   570 
   722 
   571 /**
       
   572  * Marks tile dirty if it is a canal tile.
       
   573  * Called to avoid glitches when flooding tiles next to canal tile.
       
   574  *
       
   575  * @param tile tile to check
       
   576  */
       
   577 static inline void MarkTileDirtyIfCanal(TileIndex tile) {
       
   578 	if (IsTileType(tile, MP_WATER) && IsCanal(tile)) MarkTileDirtyByTile(tile);
       
   579 }
       
   580 
       
   581 /**
       
   582  * Floods neighboured floodable tiles
       
   583  *
       
   584  * @param tile The water source tile that causes the flooding.
       
   585  * @param offs[0] Destination tile to flood.
       
   586  * @param offs[1] First corner of edge between source and dest tile.
       
   587  * @param offs[2] Second corder of edge between source and dest tile.
       
   588  * @param offs[3] Third corner of dest tile.
       
   589  * @param offs[4] Fourth corner of dest tile.
       
   590  */
       
   591 static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
       
   592 {
       
   593 	TileIndex target = TILE_ADD(tile, ToTileIndexDiff(offs[0]));
       
   594 
       
   595 	/* type of this tile mustn't be water already. */
       
   596 	if (IsTileType(target, MP_WATER)) return;
       
   597 
       
   598 	/* Are both corners of the edge between source and dest on height 0 ? */
       
   599 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[1]))) != 0 ||
       
   600 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[2]))) != 0) {
       
   601 		return;
       
   602 	}
       
   603 
       
   604 	/* Is any corner of the dest tile raised? (First two corners already checked above. */
       
   605 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[3]))) != 0 ||
       
   606 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[4]))) != 0) {
       
   607 		/* make coast.. */
       
   608 		switch (GetTileType(target)) {
       
   609 			case MP_RAILWAY: {
       
   610 				if (!IsPlainRailTile(target)) break;
       
   611 
       
   612 				FloodHalftile(target);
       
   613 
       
   614 				Vehicle *v = FindFloodableVehicleOnTile(target);
       
   615 				if (v != NULL) FloodVehicle(v);
       
   616 
       
   617 				break;
       
   618 			}
       
   619 
       
   620 			case MP_CLEAR:
       
   621 			case MP_TREES:
       
   622 				_current_player = OWNER_WATER;
       
   623 				if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
       
   624 					MakeShore(target);
       
   625 					MarkTileDirtyByTile(target);
       
   626 				}
       
   627 				break;
       
   628 
       
   629 			default:
       
   630 				break;
       
   631 		}
       
   632 	} else {
       
   633 		/* Flood vehicles */
       
   634 		_current_player = OWNER_WATER;
       
   635 
       
   636 		Vehicle *v = FindFloodableVehicleOnTile(target);
       
   637 		if (v != NULL) FloodVehicle(v);
       
   638 
       
   639 		/* flood flat tile */
       
   640 		if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
       
   641 			MakeWater(target);
       
   642 			MarkTileDirtyByTile(target);
       
   643 			/* Mark surrounding canal tiles dirty too to avoid glitches */
       
   644 			MarkTileDirtyIfCanal(target + TileDiffXY(0, 1));
       
   645 			MarkTileDirtyIfCanal(target + TileDiffXY(1, 0));
       
   646 			MarkTileDirtyIfCanal(target + TileDiffXY(0, -1));
       
   647 			MarkTileDirtyIfCanal(target + TileDiffXY(-1, 0));
       
   648 		}
       
   649 	}
       
   650 }
       
   651 
   723 
   652 /**
   724 /**
   653  * Finds a vehicle to flood.
   725  * Finds a vehicle to flood.
   654  * It does not find vehicles that are already crashed on bridges, i.e. flooded.
   726  * It does not find vehicles that are already crashed on bridges, i.e. flooded.
   655  * @param tile the tile where to find a vehicle to flood
   727  * @param tile the tile where to find a vehicle to flood
   728 
   800 
   729 			/* crash all wagons, and count passengers */
   801 			/* crash all wagons, and count passengers */
   730 			BEGIN_ENUM_WAGONS(v)
   802 			BEGIN_ENUM_WAGONS(v)
   731 				if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.Count();
   803 				if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.Count();
   732 				v->vehstatus |= VS_CRASHED;
   804 				v->vehstatus |= VS_CRASHED;
   733 				MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
   805 				MarkSingleVehicleDirty(v);
   734 			END_ENUM_WAGONS(v)
   806 			END_ENUM_WAGONS(v)
   735 
   807 
   736 			v = u;
   808 			v = u;
   737 
   809 
   738 			switch (v->type) {
   810 			switch (v->type) {
   756 			RebuildVehicleLists();
   828 			RebuildVehicleLists();
   757 		} else {
   829 		} else {
   758 			return;
   830 			return;
   759 		}
   831 		}
   760 
   832 
   761 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   833 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   762 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   834 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   763 
   835 
   764 		SetDParam(0, pass);
   836 		SetDParam(0, pass);
   765 		AddNewsItem(STR_B006_FLOOD_VEHICLE_DESTROYED,
   837 		AddNewsItem(STR_B006_FLOOD_VEHICLE_DESTROYED,
   766 			NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
   838 			NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
   770 		SndPlayVehicleFx(SND_12_EXPLOSION, v);
   842 		SndPlayVehicleFx(SND_12_EXPLOSION, v);
   771 	}
   843 	}
   772 }
   844 }
   773 
   845 
   774 /**
   846 /**
       
   847  * Returns the behaviour of a tile during flooding.
       
   848  *
       
   849  * @return Behaviour of the tile
       
   850  */
       
   851 static FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
       
   852 {
       
   853 	/* FLOOD_ACTIVE:  'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, rail with flooded halftile
       
   854 	 * FLOOD_DRYUP:   coast with more than one corner raised, coast with rail-track, coast with trees
       
   855 	 * FLOOD_PASSIVE: oilrig, dock, water-industries
       
   856 	 * FLOOD_NONE:    canals, rivers, everything else
       
   857 	 */
       
   858 	switch (GetTileType(tile)) {
       
   859 		case MP_WATER:
       
   860 			if (IsCoast(tile)) {
       
   861 				Slope tileh = GetTileSlope(tile, NULL);
       
   862 				return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
       
   863 			} else {
       
   864 				return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
       
   865 			}
       
   866 
       
   867 		case MP_RAILWAY:
       
   868 			if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
       
   869 				return (IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
       
   870 			}
       
   871 			return FLOOD_NONE;
       
   872 
       
   873 		case MP_TREES:
       
   874 			return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
       
   875 
       
   876 		case MP_STATION:
       
   877 			if (IsBuoy(tile) && GetWaterClass(tile) == WATER_CLASS_SEA) return FLOOD_ACTIVE;
       
   878 			if (IsOilRig(tile) || IsDock(tile)) return FLOOD_PASSIVE;
       
   879 			return FLOOD_NONE;
       
   880 
       
   881 		case MP_INDUSTRY:
       
   882 			return ((GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0 ? FLOOD_PASSIVE : FLOOD_NONE);
       
   883 
       
   884 		default:
       
   885 			return FLOOD_NONE;
       
   886 	}
       
   887 }
       
   888 
       
   889 /**
       
   890  * Floods a tile.
       
   891  */
       
   892 static void DoFloodTile(TileIndex target)
       
   893 {
       
   894 	if (IsTileType(target, MP_WATER)) return;
       
   895 
       
   896 	bool flooded = false; // Will be set to true if something is changed.
       
   897 
       
   898 	_current_player = OWNER_WATER;
       
   899 
       
   900 	Slope tileh = GetTileSlope(target, NULL);
       
   901 	if (tileh != SLOPE_FLAT) {
       
   902 		/* make coast.. */
       
   903 		switch (GetTileType(target)) {
       
   904 			case MP_RAILWAY: {
       
   905 				if (!IsPlainRailTile(target)) break;
       
   906 
       
   907 				flooded = FloodHalftile(target);
       
   908 
       
   909 				Vehicle *v = FindFloodableVehicleOnTile(target);
       
   910 				if (v != NULL) FloodVehicle(v);
       
   911 
       
   912 				break;
       
   913 			}
       
   914 
       
   915 			case MP_TREES:
       
   916 				if (!IsSlopeWithOneCornerRaised(tileh)) {
       
   917 					SetTreeGroundDensity(target, TREE_GROUND_SHORE, 3);
       
   918 					MarkTileDirtyByTile(target);
       
   919 					flooded = true;
       
   920 					break;
       
   921 				}
       
   922 			/* FALL THROUGH */
       
   923 			case MP_CLEAR:
       
   924 				if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
       
   925 					MakeShore(target);
       
   926 					MarkTileDirtyByTile(target);
       
   927 					flooded = true;
       
   928 				}
       
   929 				break;
       
   930 
       
   931 			default:
       
   932 				break;
       
   933 		}
       
   934 	} else {
       
   935 		/* Flood vehicles */
       
   936 		Vehicle *v = FindFloodableVehicleOnTile(target);
       
   937 		if (v != NULL) FloodVehicle(v);
       
   938 
       
   939 		/* flood flat tile */
       
   940 		if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
       
   941 			MakeWater(target);
       
   942 			MarkTileDirtyByTile(target);
       
   943 			flooded = true;
       
   944 		}
       
   945 	}
       
   946 
       
   947 	if (flooded) {
       
   948 		/* Mark surrounding canal tiles dirty too to avoid glitches */
       
   949 		MarkCanalsAndRiversAroundDirty(target);
       
   950 
       
   951 		/* update signals if needed */
       
   952 		UpdateSignalsInBuffer();
       
   953 	}
       
   954 
       
   955 	_current_player = OWNER_NONE;
       
   956 }
       
   957 
       
   958 /**
       
   959  * Drys a tile up.
       
   960  */
       
   961 static void DoDryUp(TileIndex tile)
       
   962 {
       
   963 	_current_player = OWNER_WATER;
       
   964 
       
   965 	switch (GetTileType(tile)) {
       
   966 		case MP_RAILWAY:
       
   967 			assert(IsPlainRailTile(tile));
       
   968 			assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
       
   969 
       
   970 			RailGroundType new_ground;
       
   971 			switch (GetTrackBits(tile)) {
       
   972 				case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
       
   973 				case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
       
   974 				case TRACK_BIT_LEFT:  new_ground = RAIL_GROUND_FENCE_VERT1;  break;
       
   975 				case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2;  break;
       
   976 				default: NOT_REACHED();
       
   977 			}
       
   978 			SetRailGroundType(tile, new_ground);
       
   979 			MarkTileDirtyByTile(tile);
       
   980 			break;
       
   981 
       
   982 		case MP_TREES:
       
   983 			SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3);
       
   984 			MarkTileDirtyByTile(tile);
       
   985 			break;
       
   986 
       
   987 		case MP_WATER:
       
   988 			assert(IsCoast(tile));
       
   989 
       
   990 			if (CmdSucceeded(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
       
   991 				MakeClear(tile, CLEAR_GRASS, 3);
       
   992 				MarkTileDirtyByTile(tile);
       
   993 			}
       
   994 			break;
       
   995 
       
   996 		default: NOT_REACHED();
       
   997 	}
       
   998 
       
   999 	_current_player = OWNER_NONE;
       
  1000 }
       
  1001 
       
  1002 /**
   775  * Let a water tile floods its diagonal adjoining tiles
  1003  * Let a water tile floods its diagonal adjoining tiles
   776  * called from tunnelbridge_cmd, and by TileLoop_Industry() and TileLoop_Track()
  1004  * called from tunnelbridge_cmd, and by TileLoop_Industry() and TileLoop_Track()
   777  *
  1005  *
   778  * @param tile the water/shore tile that floods
  1006  * @param tile the water/shore tile that floods
   779  */
  1007  */
   780 void TileLoop_Water(TileIndex tile)
  1008 void TileLoop_Water(TileIndex tile)
   781 {
  1009 {
   782 	static const TileIndexDiffC _tile_loop_offs_array[][5] = {
  1010 	switch (GetFloodingBehaviour(tile)) {
   783 		// tile to mod              shore?    shore?
  1011 		case FLOOD_ACTIVE:
   784 		{{-1,  0}, {0, 0}, {0, 1}, {-1,  0}, {-1,  1}},
  1012 			for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
   785 		{{ 0,  1}, {0, 1}, {1, 1}, { 0,  2}, { 1,  2}},
  1013 				TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(dir));
   786 		{{ 1,  0}, {1, 0}, {1, 1}, { 2,  0}, { 2,  1}},
  1014 				if (dest == INVALID_TILE) continue;
   787 		{{ 0, -1}, {0, 0}, {1, 0}, { 0, -1}, { 1, -1}}
  1015 
   788 	};
  1016 				uint z_dest;
   789 
  1017 				Slope slope_dest = (Slope)(GetFoundationSlope(dest, &z_dest) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP);
   790 	/* Ensure buoys on canal borders do not flood */
  1018 				if (z_dest > 0) continue;
   791 	if (IsCanalBuoyTile(tile)) return;
  1019 
   792 	/* Ensure only sea and coast floods, not canals or rivers */
  1020 				if (!HasBit(_flood_from_dirs[slope_dest], ReverseDir(dir))) continue;
   793 	if (IsTileType(tile, MP_WATER) && !(IsSea(tile) || IsCoast(tile))) return;
  1021 
   794 
  1022 				DoFloodTile(dest);
   795 	/* floods in all four diagonal directions with the exception of the edges */
  1023 			}
   796 	if (IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1) &&
  1024 			break;
   797 			IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) {
  1025 
   798 		uint i;
  1026 		case FLOOD_DRYUP: {
   799 
  1027 			Slope slope_here = (Slope)(GetFoundationSlope(tile, NULL) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP);
   800 		for (i = 0; i != lengthof(_tile_loop_offs_array); i++) {
  1028 			uint check_dirs = _flood_from_dirs[slope_here];
   801 			TileLoopWaterHelper(tile, _tile_loop_offs_array[i]);
  1029 			uint dir;
       
  1030 			FOR_EACH_SET_BIT(dir, check_dirs) {
       
  1031 				TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir((Direction)dir));
       
  1032 				if (dest == INVALID_TILE) continue;
       
  1033 
       
  1034 				FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
       
  1035 				if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
       
  1036 			}
       
  1037 			DoDryUp(tile);
       
  1038 			break;
   802 		}
  1039 		}
   803 	}
  1040 
   804 
  1041 		default: return;
   805 	/* _current_player can be changed by TileLoopWaterHelper.. reset it back here */
  1042 	}
   806 	_current_player = OWNER_NONE;
  1043 }
   807 
  1044 
   808 	/* edges */
  1045 void ConvertGroundTilesIntoWaterTiles()
   809 	if (TileX(tile) == 0 && IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) { //NE
  1046 {
   810 		TileLoopWaterHelper(tile, _tile_loop_offs_array[2]);
  1047 	TileIndex tile;
   811 	}
  1048 	uint z;
   812 
  1049 	Slope slope;
   813 	if (TileX(tile) == MapSizeX() - 2 && IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) { //SW
  1050 
   814 		TileLoopWaterHelper(tile, _tile_loop_offs_array[0]);
  1051 	for (tile = 0; tile < MapSize(); ++tile) {
   815 	}
  1052 		slope = GetTileSlope(tile, &z);
   816 
  1053 		if (IsTileType(tile, MP_CLEAR) && z == 0) {
   817 	if (TileY(tile) == 0 && IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1)) { //NW
  1054 			/* Make both water for tiles at level 0
   818 		TileLoopWaterHelper(tile, _tile_loop_offs_array[1]);
  1055 			 * and make shore, as that looks much better
   819 	}
  1056 			 * during the generation. */
   820 
  1057 			switch (slope) {
   821 	if (TileY(tile) == MapSizeY() - 2 && IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1)) { //SE
  1058 				case SLOPE_FLAT:
   822 		TileLoopWaterHelper(tile, _tile_loop_offs_array[3]);
  1059 					MakeWater(tile);
       
  1060 					break;
       
  1061 
       
  1062 				case SLOPE_N:
       
  1063 				case SLOPE_E:
       
  1064 				case SLOPE_S:
       
  1065 				case SLOPE_W:
       
  1066 					MakeShore(tile);
       
  1067 					break;
       
  1068 
       
  1069 				default:
       
  1070 					uint check_dirs = _flood_from_dirs[slope & ~SLOPE_STEEP];
       
  1071 					uint dir;
       
  1072 					FOR_EACH_SET_BIT(dir, check_dirs) {
       
  1073 						TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
       
  1074 						Slope slope_dest = (Slope)(GetTileSlope(dest, NULL) & ~SLOPE_STEEP);
       
  1075 						if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
       
  1076 							MakeShore(tile);
       
  1077 							break;
       
  1078 						}
       
  1079 					}
       
  1080 					break;
       
  1081 			}
       
  1082 		}
   823 	}
  1083 	}
   824 }
  1084 }
   825 
  1085 
   826 static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode)
  1086 static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode)
   827 {
  1087 {
   830 	TrackBits ts;
  1090 	TrackBits ts;
   831 
  1091 
   832 	if (mode != TRANSPORT_WATER) return 0;
  1092 	if (mode != TRANSPORT_WATER) return 0;
   833 
  1093 
   834 	switch (GetWaterTileType(tile)) {
  1094 	switch (GetWaterTileType(tile)) {
   835 		case WATER_TILE_CLEAR: ts = TRACK_BIT_ALL; break;
  1095 		case WATER_TILE_CLEAR: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
   836 		case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
  1096 		case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
   837 		case WATER_TILE_LOCK:  ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break;
  1097 		case WATER_TILE_LOCK:  ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break;
   838 		case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
  1098 		case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
   839 		default: return 0;
  1099 		default: return 0;
   840 	}
  1100 	}