follow digging rules when converting tiles

develop
myk002 2021-06-01 11:58:32 -07:00
parent d3d5a6edd7
commit a4c86770a4
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
1 changed files with 156 additions and 31 deletions

@ -34,7 +34,7 @@ static bool unhide(int32_t x, int32_t y, int32_t z) {
return true; return true;
} }
// unhide self and adjacent tiles if hidden and flood fill unhidden state // unhide adjacent tiles if hidden and flood fill unhidden state
static void flood_unhide(int32_t x, int32_t y, int32_t z) { static void flood_unhide(int32_t x, int32_t y, int32_t z) {
df::tiletype tt = *Maps::getTileType(x, y, z); df::tiletype tt = *Maps::getTileType(x, y, z);
if (tileShape(tt) == df::tiletype_shape::WALL if (tileShape(tt) == df::tiletype_shape::WALL
@ -90,63 +90,186 @@ static void propagate_vertical_flags(int32_t x, int32_t y, int32_t z) {
} }
} }
static bool can_dig_default(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape == df::tiletype_shape::WALL ||
shape == df::tiletype_shape::FORTIFICATION ||
shape == df::tiletype_shape::RAMP ||
shape == df::tiletype_shape::STAIR_UP ||
shape == df::tiletype_shape::STAIR_UPDOWN;
}
static bool can_dig_channel(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape != df::tiletype_shape::EMPTY &&
shape != df::tiletype_shape::ENDLESS_PIT &&
shape != df::tiletype_shape::NONE &&
shape != df::tiletype_shape::RAMP_TOP &&
shape != df::tiletype_shape::TRUNK_BRANCH;
}
static bool can_dig_up_stair(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape == df::tiletype_shape::WALL ||
shape == df::tiletype_shape::FORTIFICATION;
}
static bool can_dig_down_stair(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape == df::tiletype_shape::BOULDER ||
shape == df::tiletype_shape::BROOK_BED ||
shape == df::tiletype_shape::BROOK_TOP ||
shape == df::tiletype_shape::FLOOR ||
shape == df::tiletype_shape::FORTIFICATION ||
shape == df::tiletype_shape::PEBBLES ||
shape == df::tiletype_shape::RAMP ||
shape == df::tiletype_shape::SAPLING ||
shape == df::tiletype_shape::SHRUB ||
shape == df::tiletype_shape::TWIG ||
shape == df::tiletype_shape::WALL;
}
static bool can_dig_up_down_stair(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape == df::tiletype_shape::WALL ||
shape == df::tiletype_shape::FORTIFICATION ||
shape == df::tiletype_shape::STAIR_UP;
}
static bool can_dig_ramp(df::tiletype tt) {
df::tiletype_shape shape = tileShape(tt);
return shape == df::tiletype_shape::WALL ||
shape == df::tiletype_shape::FORTIFICATION;
}
static void set_tile_type(int32_t x, int32_t y, int32_t z, static void set_tile_type(int32_t x, int32_t y, int32_t z,
df::tiletype target_type) { df::tiletype target_type) {
if (target_type == df::tiletype::Void)
return;
df::map_block *block = Maps::getTileBlock(x, y, z); df::map_block *block = Maps::getTileBlock(x, y, z);
block->tiletype[x&15][y&15] = target_type; block->tiletype[x&15][y&15] = target_type;
} }
static void remove_ramp_top(int32_t x, int32_t y, int32_t z) {
if (!Maps::ensureTileBlock(x, y, z))
return;
if (tileShape(*Maps::getTileType(x, y, z)) == df::tiletype_shape::RAMP_TOP)
set_tile_type(x, y, z, df::tiletype::OpenSpace);
}
static bool is_wall(int32_t x, int32_t y, int32_t z) {
if (!Maps::ensureTileBlock(x, y, z))
return false;
return tileShape(*Maps::getTileType(x, y, z)) == df::tiletype_shape::WALL;
}
static void clean_ramp(int32_t x, int32_t y, int32_t z) {
if (!Maps::ensureTileBlock(x, y, z))
return;
df::tiletype tt = *Maps::getTileType(x, y, z);
if (tileShape(tt) != df::tiletype_shape::RAMP)
return;
if (is_wall(x+1, y, z) || is_wall(x-1, y, z) ||
is_wall(x, y+1, z) || is_wall(x, y-1, z))
return;
remove_ramp_top(x, y, z+1);
set_tile_type(x, y, z, findSimilarTileType(tt, df::tiletype_shape::FLOOR));
}
// removes self and/or orthogonally adjacent ramps that are no longer adjacent
// to a wall
static void clean_ramps(int32_t x, int32_t y, int32_t z) {
clean_ramp(x, y, z);
clean_ramp(x-1, y, z);
clean_ramp(x+1, y, z);
clean_ramp(x, y-1, z);
clean_ramp(x, y+1, z);
}
// TODO: if requested, create boulders // TODO: if requested, create boulders
static void dig_tile(color_ostream &out, int32_t x, int32_t y, int32_t z, static bool dig_tile(color_ostream &out, int32_t x, int32_t y, int32_t z,
df::tile_dig_designation designation) { df::tile_dig_designation designation) {
df::tiletype tt = *Maps::getTileType(x, y, z); df::tiletype tt = *Maps::getTileType(x, y, z);
// TODO: handle trees
if (!isGroundMaterial(tileMaterial(tt)))
return false;
df::tiletype target_type = df::tiletype::Void; df::tiletype target_type = df::tiletype::Void;
switch(designation) { switch(designation) {
case df::tile_dig_designation::Default: case df::tile_dig_designation::Default:
target_type = findSimilarTileType(tt, df::tiletype_shape::FLOOR); // TODO: should not leave a smooth floor when removing stairs/ramps
break; if (can_dig_default(tt)) {
case df::tile_dig_designation::UpDownStair: df::tiletype_shape shape = tileShape(tt);
target_type = df::tiletype_shape target_shape = df::tiletype_shape::FLOOR;
findSimilarTileType(tt, df::tiletype_shape::STAIR_UPDOWN); if (shape == df::tiletype_shape::STAIR_UPDOWN)
target_shape = df::tiletype_shape::STAIR_DOWN;
else if (shape == df::tiletype_shape::RAMP)
remove_ramp_top(x, y, z+1);
target_type = findSimilarTileType(tt, target_shape);
}
break; break;
case df::tile_dig_designation::Channel: case df::tile_dig_designation::Channel:
{ if (can_dig_channel(tt)) {
if (Maps::ensureTileBlock(x, y, z+1)) { remove_ramp_top(x, y, z+1);
df::tiletype tt_above = *Maps::getTileType(x, y, z+1); target_type = df::tiletype::OpenSpace;
if (tileShape(tt_above) == df::tiletype_shape::RAMP_TOP) if (Maps::ensureTileBlock(x, y, z-1) &&
set_tile_type(x, y, z+1, tiletype::OpenSpace); dig_tile(out, x, y, z-1,
} df::tile_dig_designation::Ramp)) {
target_type = tiletype::OpenSpace; // if we successfully dug out the ramp below, that took care
if (Maps::ensureTileBlock(x, y, z-1)) { // of the ramp top here
df::tiletype tt_below = *Maps::getTileType(x, y, z-1); target_type = df::tiletype::Void;
if (tileShape(tt_below) == df::tiletype_shape::WALL clean_ramps(x, y, z-1);
&& isGroundMaterial(tileMaterial(tt_below))) {
dig_tile(out, x, y, z-1, df::tile_dig_designation::Ramp);
target_type =
findSimilarTileType(tt, df::tiletype_shape::RAMP_TOP);
} }
break;
} }
break; case df::tile_dig_designation::UpStair:
} if (can_dig_up_stair(tt))
case df::tile_dig_designation::Ramp: target_type =
target_type = findSimilarTileType(tt, df::tiletype_shape::RAMP); findSimilarTileType(tt, df::tiletype_shape::STAIR_UP);
break; break;
case df::tile_dig_designation::DownStair: case df::tile_dig_designation::DownStair:
target_type = findSimilarTileType(tt, df::tiletype_shape::STAIR_DOWN); if (can_dig_down_stair(tt)) {
target_type =
findSimilarTileType(tt, df::tiletype_shape::STAIR_DOWN);
}
break; break;
case df::tile_dig_designation::UpStair: case df::tile_dig_designation::UpDownStair:
target_type = findSimilarTileType(tt, df::tiletype_shape::STAIR_UP); if (can_dig_up_down_stair(tt)) {
target_type =
findSimilarTileType(tt,
df::tiletype_shape::STAIR_UPDOWN);
}
break; break;
case df::tile_dig_designation::Ramp:
{
if (can_dig_ramp(tt)) {
target_type = findSimilarTileType(tt, df::tiletype_shape::RAMP);
if (target_type != tt && Maps::ensureTileBlock(x, y, z+1)) {
// set tile type directly instead of calling dig_tile
// because we need to use *this* tile's material, not the
// material of the tile above
set_tile_type(x, y, z+1,
findSimilarTileType(tt,
df::tiletype_shape::RAMP_TOP));
}
}
break;
}
case df::tile_dig_designation::No: case df::tile_dig_designation::No:
default: default:
out.printerr( out.printerr(
"unhandled dig designation for tile (%d, %d, %d): %d\n", "unhandled dig designation for tile (%d, %d, %d): %d\n",
x, y, z, designation); x, y, z, designation);
return;
} }
// fail if no change to tile
if (target_type == df::tiletype::Void || target_type == tt)
return false;
// TODO: set tile to use layer material // TODO: set tile to use layer material
set_tile_type(x, y, z, target_type); set_tile_type(x, y, z, target_type);
@ -154,6 +277,8 @@ static void dig_tile(color_ostream &out, int32_t x, int32_t y, int32_t z,
unhide(x, y, z); unhide(x, y, z);
flood_unhide(x, y, z); // in case we breached a cavern flood_unhide(x, y, z); // in case we breached a cavern
propagate_vertical_flags(x, y, z); // for new channels propagate_vertical_flags(x, y, z); // for new channels
return true;
} }
static void smooth_tile(color_ostream &out, int32_t x, int32_t y, int32_t z, static void smooth_tile(color_ostream &out, int32_t x, int32_t y, int32_t z,