From c990def894429c43df0f977661287489a3d3c406 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 13 Feb 2023 17:35:17 -0800 Subject: [PATCH] Adds a designation buffer in dig-now's processing algorithm This may fix the issue seen when channeling consecutive layers, needs to be tested --- plugins/dig-now.cpp | 123 ++++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/plugins/dig-now.cpp b/plugins/dig-now.cpp index 9f961c817..2f63c54da 100644 --- a/plugins/dig-now.cpp +++ b/plugins/dig-now.cpp @@ -15,6 +15,7 @@ #include "modules/Random.h" #include "modules/Units.h" #include "modules/World.h" +#include "modules/EventManager.h" #include #include @@ -28,6 +29,7 @@ #include #include +#include DFHACK_PLUGIN("dig-now"); REQUIRE_GLOBAL(plotinfo); @@ -46,6 +48,31 @@ namespace DFHack { using namespace DFHack; +struct designation{ + df::coord pos; + df::tile_designation type; + df::tile_occupancy occupancy; + designation(const df::coord &c, const df::tile_designation &td, const df::tile_occupancy &to) : pos(c), type(td), occupancy(to) {} + + bool operator==(const designation &rhs) const { + return pos == rhs.pos; + } + + bool operator!=(const designation &rhs) const { + return !(rhs == *this); + } +}; + +namespace std { + template<> + struct hash { + std::size_t operator()(const designation &c) const { + std::hash hash_coord; + return hash_coord(c.pos); + } + }; +} + struct boulder_percent_options { // percent chance ([0..100]) for creating a boulder for the given rock type uint32_t layer; @@ -367,7 +394,7 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, // todo: does can_dig_channel return false? if (can_dig_channel(tt) && map.ensureBlockAt(pos_below) && is_diggable(map, pos_below, map.tiletypeAt(pos_below))) { - TRACE(channels).print("dig_tile: channeling at (" COORD ")\n",COORDARGS(pos_below)); + TRACE(channels).print("dig_tile: channeling at (" COORD ") [can_dig_channel: true]\n",COORDARGS(pos_below)); target_type = df::tiletype::OpenSpace; DFCoord pos_above(pos.x, pos.y, pos.z+1); if (map.ensureBlockAt(pos_above)) { @@ -375,17 +402,16 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, } df::tile_dig_designation td_below = map.designationAt(pos_below).bits.dig; - // todo: what is this chain of dig_tile(below)? + // todo: digging to floor below? if (dig_tile(out, map, pos_below, df::tile_dig_designation::Ramp, dug_tiles)) { clean_ramps(map, pos_below); if (td_below == df::tile_dig_designation::Default) { - // todo: removing ramp? dig_tile(out, map, pos_below, td_below, dug_tiles); } return true; } } else { - DEBUG(channels).print("dig_tile: failed to channel at (" COORD ")\n", COORDARGS(pos_below)); + DEBUG(channels).print("dig_tile: failed to channel at (" COORD ") [can_dig_channel: false]\n", COORDARGS(pos_below)); } break; } @@ -630,6 +656,7 @@ static void do_dig(color_ostream &out, std::vector &dug_coords, rng.init(); + std::unordered_set buffer; // go down levels instead of up so stacked ramps behave as expected for (int16_t z = options.end.z; z >= options.start.z; --z) { for (int16_t y = options.start.y; y <= options.end.y; ++y) { @@ -646,48 +673,58 @@ static void do_dig(color_ostream &out, std::vector &dug_coords, DFCoord pos(x, y, z); df::tile_designation td = map.designationAt(pos); df::tile_occupancy to = map.occupancyAt(pos); - if (td.bits.dig != df::tile_dig_designation::No && !to.bits.dig_marked) { - std::vector dug_tiles; - - // todo: check why dig_tile doesn't dig the second layer of channels - if (dig_tile(out, map, pos, td.bits.dig, dug_tiles)) { - for (auto info: dug_tiles) { - td = map.designationAt(info.pos); - td.bits.dig = df::tile_dig_designation::No; - map.setDesignationAt(info.pos, td); - - dug_coords.push_back(info.pos); - refresh_adjacent_smooth_walls(map, info.pos); - if (info.imat < 0) - continue; - if (produces_item(options.boulder_percents, - map, rng, info)) { - auto k = std::make_pair(info.itype, info.imat); - item_coords[k].push_back(info.pos); - } - } - } - // todo: check mark mode of smooth designations - } else if (td.bits.smooth == 1) { - if (smooth_tile(out, map, pos)) { - to = map.occupancyAt(pos); - td.bits.smooth = 0; - map.setDesignationAt(pos, td); - } - } else if (to.bits.carve_track_north == 1 - || to.bits.carve_track_east == 1 - || to.bits.carve_track_south == 1 - || to.bits.carve_track_west == 1) { - if (carve_tile(map, pos, to)) { - to = map.occupancyAt(pos); - to.bits.carve_track_north = 0; - to.bits.carve_track_east = 0; - to.bits.carve_track_south = 0; - to.bits.carve_track_west = 0; - map.setOccupancyAt(pos, to); + + // we're only buffering designations, so that processing doesn't affect what we're buffering + buffer.emplace(pos, td, to); + } + } + } + + // process designations + for(auto &d : buffer) { + auto pos = d.pos; + auto td = d.type; + auto to = d.occupancy; + + if (td.bits.dig != df::tile_dig_designation::No && !to.bits.dig_marked) { + std::vector dug_tiles; + + if (dig_tile(out, map, pos, td.bits.dig, dug_tiles)) { + for (auto info: dug_tiles) { + td = map.designationAt(info.pos); + td.bits.dig = df::tile_dig_designation::No; + map.setDesignationAt(info.pos, td); + + dug_coords.push_back(info.pos); + refresh_adjacent_smooth_walls(map, info.pos); + if (info.imat < 0) + continue; + if (produces_item(options.boulder_percents, + map, rng, info)) { + auto k = std::make_pair(info.itype, info.imat); + item_coords[k].push_back(info.pos); } } } + // todo: check mark mode of smooth designations + } else if (td.bits.smooth == 1) { + if (smooth_tile(out, map, pos)) { + to = map.occupancyAt(pos); + td.bits.smooth = 0; + map.setDesignationAt(pos, td); + } + } else if (to.bits.carve_track_north == 1 + || to.bits.carve_track_east == 1 + || to.bits.carve_track_south == 1 + || to.bits.carve_track_west == 1) { + if (carve_tile(map, pos, to)) { + to = map.occupancyAt(pos); + to.bits.carve_track_north = 0; + to.bits.carve_track_east = 0; + to.bits.carve_track_south = 0; + to.bits.carve_track_west = 0; + map.setOccupancyAt(pos, to); + } } }