From c1dcaa43786422b9c18cbc525e5a9c623e05a7ad Mon Sep 17 00:00:00 2001 From: myk002 Date: Sun, 6 Jun 2021 05:52:20 -0700 Subject: [PATCH] generate gems as ROUGH, not BOULDER also fix missing dug_tile indices when channels are dug also fix second boulder/gem being generated with a potentially incorrect probability when digging channels and ramps --- plugins/dig-now.cpp | 152 ++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 70 deletions(-) diff --git a/plugins/dig-now.cpp b/plugins/dig-now.cpp index c9a218aae..2841a9888 100644 --- a/plugins/dig-now.cpp +++ b/plugins/dig-now.cpp @@ -237,29 +237,39 @@ static void clean_ramps(MapExtras::MapCache &map, const DFCoord &pos) { clean_ramp(map, DFCoord(pos.x, pos.y+1, pos.z)); } -// returns material type of prospective boulders generated by the wall tile at -// the given position, or -1 if not a boulderable wall -static int16_t get_boulder_mat(MapExtras::MapCache &map, const DFCoord &pos) { - df::tiletype tt = map.tiletypeAt(pos); - df::tiletype_shape shape = tileShape(tt); - df::tiletype_material tmat = tileMaterial(tt); - - if (shape != df::tiletype_shape::WALL - || (tmat != df::tiletype_material::STONE - && tmat != df::tiletype_material::MINERAL)) - return -1; - - t_matpair matpair; - if (map.isVeinAt(pos)) - matpair = map.veinMaterialAt(pos); - else if (map.isLayerAt(pos)) - matpair = map.layerMaterialAt(pos); - return matpair.mat_type; -} +struct dug_tile_info { + DFCoord pos; + df::tiletype_material tmat; + df::item_type itype; + int32_t imat; // mat idx of boulder/gem potentially generated at this pos + + dug_tile_info(MapExtras::MapCache &map, const DFCoord &pos) { + this->pos = pos; + + df::tiletype tt = map.tiletypeAt(pos); + tmat = tileMaterial(tt); + + switch (map.BlockAtTile(pos)->veinTypeAt(pos)) { + case df::inclusion_type::CLUSTER_ONE: + case df::inclusion_type::CLUSTER_SMALL: + itype = df::item_type::ROUGH; + break; + default: + itype = df::item_type::BOULDER; + } + + imat = -1; + if (tileShape(tt) == df::tiletype_shape::WALL + && (tmat == df::tiletype_material::STONE + || tmat == df::tiletype_material::MINERAL + || tmat == df::tiletype_material::FEATURE)) + imat = map.baseMaterialAt(pos).mat_index; + } +}; static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, const DFCoord &pos, df::tile_dig_designation designation, - int16_t *boulder_mat) { + std::vector &dug_tiles) { df::tiletype tt = map.tiletypeAt(pos); // TODO: handle tree trunks, roots, and surface tiles @@ -267,8 +277,6 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, if (!isGroundMaterial(tile_mat)) return false; - *boulder_mat = get_boulder_mat(map, pos); - df::tiletype target_type = df::tiletype::Void; switch(designation) { case df::tile_dig_designation::Default: @@ -284,15 +292,14 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, break; case df::tile_dig_designation::Channel: if (can_dig_channel(tt)) { - remove_ramp_top(map, DFCoord(pos.x, pos.y, pos.z+1)); target_type = df::tiletype::OpenSpace; DFCoord pos_below(pos.x, pos.y, pos.z-1); if (map.ensureBlockAt(pos_below) && dig_tile(out, map, pos_below, - df::tile_dig_designation::Ramp, boulder_mat)) { + df::tile_dig_designation::Ramp, dug_tiles)) { clean_ramps(map, pos_below); // if we successfully dug out the ramp below, that took care - // of the ramp top here + // of adding the ramp top here return true; } break; @@ -321,13 +328,17 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, if (can_dig_ramp(tt)) { target_type = findSimilarTileType(tt, df::tiletype_shape::RAMP); DFCoord pos_above(pos.x, pos.y, pos.z+1); - boulder_mat[1] = get_boulder_mat(map, pos_above); if (target_type != tt && map.ensureBlockAt(pos_above)) { + // only capture the tile info of pos_above if we didn't get + // here via the Channel case above + if (dug_tiles.size() == 0) + dug_tiles.push_back(dug_tile_info(map, pos_above)); // set tile type directly instead of calling dig_shape // because we need to use *this* tile's material, not the // material of the tile above map.setTiletypeAt(pos_above, findSimilarTileType(tt, df::tiletype_shape::RAMP_TOP)); + remove_ramp_top(map, DFCoord(pos.x, pos.y, pos.z+2)); } } break; @@ -343,6 +354,7 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, if (target_type == df::tiletype::Void || target_type == tt) return false; + dug_tiles.push_back(dug_tile_info(map, pos)); dig_type(map, pos, target_type); // let light filter down to newly exposed tiles @@ -428,42 +440,45 @@ static bool carve_tile(MapExtras::MapCache &map, return true; } -static bool produces_boulder(const boulder_percent_options &options, - Random::MersenneRNG &rng, - df::tiletype_material tmat, - df::inclusion_type vein_type) { +static bool produces_item(const boulder_percent_options &options, + MapExtras::MapCache &map, Random::MersenneRNG &rng, + const dug_tile_info &info) { uint32_t probability; - switch (vein_type) { - case df::inclusion_type::CLUSTER: - case df::inclusion_type::VEIN: - probability = options.vein; - break; - case df::inclusion_type::CLUSTER_ONE: - case df::inclusion_type::CLUSTER_SMALL: - probability = options.small_cluster; - break; - default: - probability = options.layer; - break; - } - - if (tmat == df::tiletype_material::FEATURE) + if (info.tmat == df::tiletype_material::FEATURE) probability = options.deep; + else { + switch (map.BlockAtTile(info.pos)->veinTypeAt(info.pos)) { + case df::inclusion_type::CLUSTER: + case df::inclusion_type::VEIN: + probability = options.vein; + break; + case df::inclusion_type::CLUSTER_ONE: + case df::inclusion_type::CLUSTER_SMALL: + probability = options.small_cluster; + break; + default: + probability = options.layer; + break; + } + } return rng.random(100) < probability; } +typedef std::map, std::vector> + item_coords_t; + static void do_dig(color_ostream &out, std::vector &dug_coords, - std::map> &boulder_coords, - const dig_now_options &options) { + item_coords_t &item_coords, const dig_now_options &options) { MapExtras::MapCache map; Random::MersenneRNG rng; rng.init(); - for (uint32_t z = options.start.z; z <= options.end.z; ++z) { - for (uint32_t y = options.start.y; y <= options.end.y; ++y) { - for (uint32_t x = options.start.x; x <= options.end.x; ++x) { + // 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) { + for (int16_t x = options.start.x; x <= options.end.x; ++x) { // this will return NULL if the map block hasn't been allocated // yet, but that means there aren't any designations anyway. if (!Maps::getTileBlock(x, y, z)) @@ -473,21 +488,19 @@ static void do_dig(color_ostream &out, std::vector &dug_coords, df::tile_designation td = map.designationAt(pos); df::tile_occupancy to = map.occupancyAt(pos); if (td.bits.dig != df::tile_dig_designation::No) { - int16_t boulder_mat[2]; - memset(boulder_mat, -1, sizeof(boulder_mat)); - df::tiletype_material tmat = - tileMaterial(map.tiletypeAt(pos)); - if (dig_tile(out, map, pos, td.bits.dig, boulder_mat)) { + std::vector dug_tiles; + if (dig_tile(out, map, pos, td.bits.dig, dug_tiles)) { td = map.designationAt(pos); td.bits.dig = df::tile_dig_designation::No; map.setDesignationAt(pos, td); - dug_coords.push_back(pos); - for (size_t i = 0; i < 2; ++i) { - if (boulder_mat[i] < 0) + for (auto info : dug_tiles) { + dug_coords.push_back(info.pos); + if (info.imat < 0) continue; - if (produces_boulder(options.boulder_percents, rng, - tmat, map.BlockAtTile(pos)->veinTypeAt(pos))) { - boulder_coords[boulder_mat[i]].push_back(pos); + 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); } } } @@ -535,7 +548,7 @@ static DFCoord simulate_fall(const DFCoord &pos) { } static void create_boulders(color_ostream &out, - const std::map> &boulder_coords, + const item_coords_t &item_coords, const dig_now_options &options) { df::unit *unit = world->units.active[0]; df::historical_entity *civ = df::historical_entity::find(unit->civ_id); @@ -553,15 +566,15 @@ static void create_boulders(color_ostream &out, " option specifies an open, non-wall tile."); } - for (auto entry : boulder_coords) { + for (auto entry : item_coords) { df::reaction_product_itemst *prod = df::allocate(); const std::vector &coords = entry.second; - prod->item_type = df::item_type::BOULDER; + prod->item_type = entry.first.first; prod->item_subtype = -1; prod->mat_type = 0; - prod->mat_index = entry.first; + prod->mat_index = entry.first.second; prod->probability = 100; prod->count = coords.size(); prod->product_dimension = 1; @@ -670,13 +683,12 @@ command_result dig_now(color_ostream &out, std::vector ¶ms) { return CR_FAILURE; } - // track which positions were modified and where to produce boulders of a - // given material + // track which positions were modified and where to produce items std::vector dug_coords; - std::map> boulder_coords; + item_coords_t item_coords; - do_dig(out, dug_coords, boulder_coords, options); - create_boulders(out, boulder_coords, options); + do_dig(out, dug_coords, item_coords, options); + create_boulders(out, item_coords, options); unhide_dug_tiles(out, dug_coords); // force the game to recompute its walkability cache