From f35b0e6aceeb0279d182e5e7f1451e9d98639675 Mon Sep 17 00:00:00 2001 From: jensj12 Date: Thu, 13 Jul 2017 16:54:37 +0200 Subject: [PATCH] Replace mountain tool algorithm Fixes #2225. The mountain tool will now stop at land edges. It also improves the performance of the mountain tool. --- src/openrct2/world/map.c | 499 +++++++++++++++++++++------------------ 1 file changed, 269 insertions(+), 230 deletions(-) diff --git a/src/openrct2/world/map.c b/src/openrct2/world/map.c index b6904763bf..6027687fc6 100644 --- a/src/openrct2/world/map.c +++ b/src/openrct2/world/map.c @@ -2093,63 +2093,192 @@ void game_command_lower_land(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, ); } -/** - * - * rct2: 0x0068C3B2 slope 1, style 0 - * rct2: 0x0068C47A slope 2, style 1 - * rct2: 0x0068C222 slope 4, style 2 - * rct2: 0x0068C2EA slope 8, style 3 - */ -static money32 smooth_land_tile(sint32 direction, uint8 flags, sint32 x, sint32 y, sint32 targetBaseZ, sint32 minBaseZ) +static money32 smooth_land_tile(sint32 direction, uint8 flags, sint32 x, sint32 y, rct_map_element * mapElement, bool raiseLand) { - // Check if inside map bounds - if (!map_is_location_valid(x, y)) { - return MONEY32_UNDEFINED; - } - - // Get height of tile - rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); - if (mapElement == NULL) - { - log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y); - return MONEY32_UNDEFINED; - } - sint32 baseZ = map_element_get_corner_height(mapElement, direction); - - // Check if tile is same height as target tile - if (baseZ == targetBaseZ) { - // No need to raise or lower - return MONEY32_UNDEFINED; - } - - uint8 style; - if (targetBaseZ <= baseZ) { - baseZ = baseZ - targetBaseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - sint32 slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_lower_styles[direction][slope]; - if (style & 0x20) { - targetBaseZ -= 2; - style &= ~0x20; - } - } else { - baseZ = targetBaseZ - baseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - sint32 slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_raise_styles[direction][slope]; - if ((style & 0x20) != 0) { + sint32 targetBaseZ = mapElement->base_height; + sint32 slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; + if (raiseLand) { + slope = map_element_raise_styles[direction][slope]; + if (slope & 0x20) { targetBaseZ += 2; - style &= ~0x20; + slope &= ~0x20; } } + else { + slope = map_element_lower_styles[direction][slope]; + if (slope & 0x20) { + targetBaseZ -= 2; + slope &= ~0x20; + } + } + return game_do_command(x, flags, y, targetBaseZ | (slope << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); +} - return game_do_command(x, flags, y, targetBaseZ | (style << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); +static money32 smooth_land_row_by_edge(sint32 flags, sint32 x, sint32 y, sint32 expectedLandHeight1, sint32 expectedLandHeight2, sint32 stepX, sint32 stepY, sint32 direction1, sint32 direction2, sint32 checkDirection1, sint32 checkDirection2, bool raiseLand) +{ + bool shouldContinue = true; + sint32 landChangePerTile = raiseLand ? -2 : 2; + rct_map_element *mapElement, *nextMapElement; + money32 totalCost = 0; + money32 result; + + // check if we need to start at all + if (!map_is_location_valid(x, y) || !map_is_location_valid(x + stepX, y + stepY)) { + return 0; + } + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + nextMapElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5); + if (mapElement == NULL || nextMapElement == NULL) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection1) != expectedLandHeight1 + (raiseLand ? -2 : 2)) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection2) != expectedLandHeight2 + (raiseLand ? -2 : 2)) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection1) != map_element_get_corner_height(nextMapElement, direction1)) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection2) != map_element_get_corner_height(nextMapElement, direction2)) { + return 0; + } + while (shouldContinue) + { + x += stepX; + y += stepY; + // check if we need to continue after raising the current tile + // this needs to be checked before the tile is changed + if (!map_is_location_valid(x + stepX, y + stepY)) { + shouldContinue = false; + } + else + { + mapElement = nextMapElement; + nextMapElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5); + if (nextMapElement == NULL) { + shouldContinue = false; + } + if (map_element_get_corner_height(mapElement, direction1) + landChangePerTile != map_element_get_corner_height(mapElement, checkDirection1)) { + shouldContinue = false; + } + if (map_element_get_corner_height(mapElement, direction2) + landChangePerTile != map_element_get_corner_height(mapElement, checkDirection2)) { + if (shouldContinue) + { + //totalCost += smooth_land_row_by_corner(flags, x, y, expectedLandHeight1, stepX, stepY, direction1, checkDirection1, raiseLand, landChangePerTile); + } + shouldContinue = false; + } + if (shouldContinue && map_element_get_corner_height(mapElement, checkDirection1) != map_element_get_corner_height(nextMapElement, direction1)) { + shouldContinue = false; + } + if (shouldContinue && map_element_get_corner_height(mapElement, checkDirection2) != map_element_get_corner_height(nextMapElement, direction2)) { + shouldContinue = false; + } + } + expectedLandHeight1 += landChangePerTile; + // change land of current tile + sint32 targetBaseZ = mapElement->base_height; + sint32 slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; + if (raiseLand) { + slope = map_element_raise_styles[direction1][slope]; + if (slope & 0x20) { + targetBaseZ += 2; + slope &= ~0x20; + } + slope = map_element_raise_styles[direction2][slope]; + if (slope & 0x20) { + targetBaseZ += 2; + slope &= ~0x20; + } + } + else + { + slope = map_element_lower_styles[direction1][slope]; + if (slope & 0x20) { + targetBaseZ -= 2; + slope &= ~0x20; + } + slope = map_element_lower_styles[direction2][slope]; + if (slope & 0x20) { + targetBaseZ -= 2; + slope &= ~0x20; + } + } + result = game_do_command(x, flags, y, targetBaseZ | (slope << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); + if (result != MONEY32_UNDEFINED) { + totalCost += result; + } + } + return totalCost; +} + +static money32 smooth_land_row_by_corner(sint32 flags, sint32 x, sint32 y, sint32 expectedLandHeight, sint32 stepX, sint32 stepY, sint32 direction, sint32 checkDirection, bool raiseLand) +{ + bool shouldContinue = true; + rct_map_element *mapElement, *nextMapElement; + money32 totalCost = 0; + money32 result; + sint32 landChangePerTile; + if (stepX == 0 || stepY == 0) + { + landChangePerTile = raiseLand ? -2 : 2; + } + else + { + landChangePerTile = raiseLand ? -4 : 4; + } + + // check if we need to start at all + if (!map_is_location_valid(x, y) || !map_is_location_valid(x + stepX, y + stepY)) { + return 0; + } + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + nextMapElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5); + if (mapElement == NULL || nextMapElement == NULL) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection) != expectedLandHeight + (raiseLand ? -2 : 2)) { + return 0; + } + if (map_element_get_corner_height(mapElement, checkDirection) != map_element_get_corner_height(nextMapElement, direction)) { + return 0; + } + while (shouldContinue) + { + x += stepX; + y += stepY; + // check if we need to continue after raising the current tile + // this needs to be checked before the tile is changed + if (!map_is_location_valid(x + stepX, y + stepY)) { + shouldContinue = false; + } + else + { + mapElement = nextMapElement; + nextMapElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5); + if (nextMapElement == NULL) { + shouldContinue = false; + } + if (map_element_get_corner_height(mapElement, direction) + landChangePerTile != map_element_get_corner_height(mapElement, checkDirection)) { + shouldContinue = false; + } + if (shouldContinue && map_element_get_corner_height(mapElement, checkDirection) != map_element_get_corner_height(nextMapElement, direction)) { + shouldContinue = false; + } + } + if (stepX*stepY != 0) { + totalCost += smooth_land_row_by_corner(flags, x, y, expectedLandHeight + (landChangePerTile / 2), 0, stepY, direction, (checkDirection + 1)%4, raiseLand); + totalCost += smooth_land_row_by_corner(flags, x, y, expectedLandHeight + (landChangePerTile / 2), stepX, 0, direction, (checkDirection + 3)%4, raiseLand); + } + expectedLandHeight += landChangePerTile; + // change land of current tile + result = smooth_land_tile(direction, flags, x, y, mapElement, raiseLand); + if (result != MONEY32_UNDEFINED) { + totalCost += result; + } + } + return totalCost; } static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32 mapLeft, sint32 mapTop, sint32 mapRight, sint32 mapBottom, sint32 command) @@ -2160,7 +2289,8 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32 mapRight = clamp(0, mapRight, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32); mapBottom = clamp(0, mapBottom, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32); - sint32 commandType; + bool raiseLand = command < 0x7FFF; + sint32 commandType = raiseLand ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; sint32 centreZ = map_element_height(centreX, centreY); sint32 mapLeftRight = mapLeft | (mapRight << 16); sint32 mapTopBottom = mapTop | (mapBottom << 16); @@ -2173,7 +2303,6 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32 money32 totalCost = 0; money32 result; - commandType = command < 0x7FFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; rct_map_element *mapElement = map_get_surface_element_at(mapLeft >> 5, mapTop >> 5); if (mapElement == NULL) @@ -2231,192 +2360,102 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32 } } - sint32 x = mapLeft; - sint32 y = mapTop; - sint32 size = ((mapRight - mapLeft) >> 5) + 1; - sint32 initialMinZ = -2; - // Then do the smoothing - // The coords go in circles around the selected tile(s) - for (; size <= MAXIMUM_MAP_SIZE_TECHNICAL; size += 2) { - initialMinZ += 2; - sint32 minZ = initialMinZ * 2; - x -= 32; - y -= 32; - - // Corner (North-West) - mapElement = map_get_surface_element_at(mapLeft >> 5, mapTop >> 5); + if (fullTile) { sint32 z = clamp(minHeight, map_element_get_corner_height(mapElement, 2), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 2); - result = smooth_land_tile(0, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - y += 32; - - // Side (West) - for (sint32 i = 0; i < size; i++) { - sint32 y2 = clamp(mapTop, y, mapBottom); - mapElement = map_get_surface_element_at(mapLeft >> 5, y2 >> 5); - if (y >= mapTop) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 3), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 3); - result = smooth_land_tile((y <= mapBottom) ? 0 : 1, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - minZ -= 2; - if (y >= mapTop) { - minZ += 2; - if (y > mapBottom) { - minZ += 2; - } - } - if (y <= mapBottom) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 2), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 2); - result = smooth_land_tile((y >= mapTop) ? 1 : 0, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - - y += 32; - } - - // Corner (South-West) + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand); mapElement = map_get_surface_element_at(mapLeft >> 5, mapBottom >> 5); z = clamp(minHeight, map_element_get_corner_height(mapElement, 3), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 3); - result = smooth_land_tile(1, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - x += 32; - - // Side (South) - for (sint32 i = 0; i < size; i++) { - sint32 x2 = clamp(mapLeft, x, mapRight); - mapElement = map_get_surface_element_at(x2 >> 5, mapBottom >> 5); - if (x >= mapLeft) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 0), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 0); - result = smooth_land_tile((x <= mapRight) ? 1 : 2, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - minZ -= 2; - if (x >= mapLeft) { - minZ += 2; - if (x > mapRight) { - minZ += 2; - } - } - if (x <= mapRight) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 3), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 3); - result = smooth_land_tile((x >= mapLeft) ? 2 : 1, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - x += 32; - } - - // Corner (South-East) + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapBottom, z, -32, 32, 1, 3, raiseLand); mapElement = map_get_surface_element_at(mapRight >> 5, mapBottom >> 5); z = clamp(minHeight, map_element_get_corner_height(mapElement, 0), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 0); - result = smooth_land_tile(2, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - y -= 32; - - // Side (East) - for (sint32 i = 0; i < size; i++) { - sint32 y2 = clamp(mapTop, y, mapBottom); - mapElement = map_get_surface_element_at(mapRight >> 5, y2 >> 5); - if (y <= mapBottom) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 1), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 1); - result = smooth_land_tile((y >= mapTop) ? 2 : 3, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - minZ -= 2; - if (y <= mapBottom) { - minZ += 2; - if (y < mapTop) { - minZ += 2; - } - } - if (y >= mapTop) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 0), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 0); - result = smooth_land_tile((y <= mapBottom) ? 3 : 2, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - - y -= 32; - } - - // Corner (North-East) + totalCost += smooth_land_row_by_corner(flags, mapRight, mapBottom, z, 32, 32, 2, 0, raiseLand); mapElement = map_get_surface_element_at(mapRight >> 5, mapTop >> 5); z = clamp(minHeight, map_element_get_corner_height(mapElement, 1), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 1); - result = smooth_land_tile(3, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; + totalCost += smooth_land_row_by_corner(flags, mapRight, mapTop, z, 32, -32, 3, 1, raiseLand); + + sint32 x = mapLeft; + sint32 y, z2; + for (y = mapTop; y <= mapBottom; y += 32) + { + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + z = clamp(minHeight, map_element_get_corner_height(mapElement, 0), maxHeight); + z2 = clamp(minHeight, map_element_get_corner_height(mapElement, 1), maxHeight); + totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, -32, 0, 0, 1, 3, 2, raiseLand); } - x -= 32; + x = mapRight; + for (y = mapTop; y <= mapBottom; y += 32) + { + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + z = clamp(minHeight, map_element_get_corner_height(mapElement, 2), maxHeight); + z2 = clamp(minHeight, map_element_get_corner_height(mapElement, 3), maxHeight); + totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 32, 0, 2, 3, 1, 0, raiseLand); + } + y = mapTop; + for (x = mapLeft; x <= mapRight; x += 32) + { + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + z = clamp(minHeight, map_element_get_corner_height(mapElement, 0), maxHeight); + z2 = clamp(minHeight, map_element_get_corner_height(mapElement, 3), maxHeight); + totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 0, -32, 0, 3, 1, 2, raiseLand); + } + y = mapBottom; + for (x = mapLeft; x <= mapRight; x += 32) + { + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + z = clamp(minHeight, map_element_get_corner_height(mapElement, 1), maxHeight); + z2 = clamp(minHeight, map_element_get_corner_height(mapElement, 2), maxHeight); + totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 0, 32, 1, 2, 0, 3, raiseLand); + } + } + else // fullTile + { + sint32 z = map_get_corner_height(newBaseZ, newSlope, 2); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 0); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 32, 2, 0, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 3); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 32, 1, 3, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 1); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, -32, 3, 1, raiseLand); - // Side (North) - for (sint32 i = 0; i < size; i++) { - sint32 x2 = clamp(mapLeft, x, mapRight); - mapElement = map_get_surface_element_at(x2 >> 5, mapTop >> 5); - if (x <= mapRight) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 2), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 2); - result = smooth_land_tile((x >= mapLeft) ? 3 : 0, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - minZ -= 2; - if (x <= mapRight) { - minZ += 2; - if (x < mapLeft) { - minZ += 2; - } - } - if (x >= mapLeft) { - z = clamp(minHeight, map_element_get_corner_height(mapElement, 1), maxHeight); - if (!fullTile) - z = map_get_corner_height(newBaseZ, newSlope, 1); - result = smooth_land_tile((x <= mapRight) ? 0 : 3, flags, x, y, z, minZ); - if (result != MONEY32_UNDEFINED) { - totalCost += result; - } - } - - x -= 32; + switch (command & 0x7FFF) { + case MAP_SELECT_TYPE_CORNER_0: + z = map_get_corner_height(newBaseZ, newSlope, 0); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 3, 0, raiseLand); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 1, 0, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 1); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 0, 1, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 3); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 0, 3, raiseLand); + break; + case MAP_SELECT_TYPE_CORNER_1: + z = map_get_corner_height(newBaseZ, newSlope, 1); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 2, 1, raiseLand); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 0, 1, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 0); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 1, 0, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 2); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 1, 2, raiseLand); + break; + case MAP_SELECT_TYPE_CORNER_2: + z = map_get_corner_height(newBaseZ, newSlope, 2); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 1, 2, raiseLand); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 3, 2, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 3); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 2, 3, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 1); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 2, 1, raiseLand); + break; + case MAP_SELECT_TYPE_CORNER_3: + z = map_get_corner_height(newBaseZ, newSlope, 3); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 0, 3, raiseLand); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 2, 3, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 2); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 3, 2, raiseLand); + z = map_get_corner_height(newBaseZ, newSlope, 0); + totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 3, 0, raiseLand); + break; } }