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
develop
myk002 2021-06-06 05:52:20 -07:00
parent 71c605afd4
commit c1dcaa4378
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
1 changed files with 82 additions and 70 deletions

@ -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)); clean_ramp(map, DFCoord(pos.x, pos.y+1, pos.z));
} }
// returns material type of prospective boulders generated by the wall tile at struct dug_tile_info {
// the given position, or -1 if not a boulderable wall DFCoord pos;
static int16_t get_boulder_mat(MapExtras::MapCache &map, const 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); df::tiletype tt = map.tiletypeAt(pos);
df::tiletype_shape shape = tileShape(tt); tmat = tileMaterial(tt);
df::tiletype_material tmat = tileMaterial(tt);
if (shape != df::tiletype_shape::WALL switch (map.BlockAtTile(pos)->veinTypeAt(pos)) {
|| (tmat != df::tiletype_material::STONE case df::inclusion_type::CLUSTER_ONE:
&& tmat != df::tiletype_material::MINERAL)) case df::inclusion_type::CLUSTER_SMALL:
return -1; itype = df::item_type::ROUGH;
break;
default:
itype = df::item_type::BOULDER;
}
t_matpair matpair; imat = -1;
if (map.isVeinAt(pos)) if (tileShape(tt) == df::tiletype_shape::WALL
matpair = map.veinMaterialAt(pos); && (tmat == df::tiletype_material::STONE
else if (map.isLayerAt(pos)) || tmat == df::tiletype_material::MINERAL
matpair = map.layerMaterialAt(pos); || tmat == df::tiletype_material::FEATURE))
return matpair.mat_type; imat = map.baseMaterialAt(pos).mat_index;
} }
};
static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, static bool dig_tile(color_ostream &out, MapExtras::MapCache &map,
const DFCoord &pos, df::tile_dig_designation designation, const DFCoord &pos, df::tile_dig_designation designation,
int16_t *boulder_mat) { std::vector<dug_tile_info> &dug_tiles) {
df::tiletype tt = map.tiletypeAt(pos); df::tiletype tt = map.tiletypeAt(pos);
// TODO: handle tree trunks, roots, and surface tiles // 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)) if (!isGroundMaterial(tile_mat))
return false; return false;
*boulder_mat = get_boulder_mat(map, pos);
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:
@ -284,15 +292,14 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map,
break; break;
case df::tile_dig_designation::Channel: case df::tile_dig_designation::Channel:
if (can_dig_channel(tt)) { if (can_dig_channel(tt)) {
remove_ramp_top(map, DFCoord(pos.x, pos.y, pos.z+1));
target_type = df::tiletype::OpenSpace; target_type = df::tiletype::OpenSpace;
DFCoord pos_below(pos.x, pos.y, pos.z-1); DFCoord pos_below(pos.x, pos.y, pos.z-1);
if (map.ensureBlockAt(pos_below) && if (map.ensureBlockAt(pos_below) &&
dig_tile(out, map, 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); clean_ramps(map, pos_below);
// if we successfully dug out the ramp below, that took care // if we successfully dug out the ramp below, that took care
// of the ramp top here // of adding the ramp top here
return true; return true;
} }
break; break;
@ -321,13 +328,17 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map,
if (can_dig_ramp(tt)) { if (can_dig_ramp(tt)) {
target_type = findSimilarTileType(tt, df::tiletype_shape::RAMP); target_type = findSimilarTileType(tt, df::tiletype_shape::RAMP);
DFCoord pos_above(pos.x, pos.y, pos.z+1); 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)) { 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 // set tile type directly instead of calling dig_shape
// because we need to use *this* tile's material, not the // because we need to use *this* tile's material, not the
// material of the tile above // material of the tile above
map.setTiletypeAt(pos_above, map.setTiletypeAt(pos_above,
findSimilarTileType(tt, df::tiletype_shape::RAMP_TOP)); findSimilarTileType(tt, df::tiletype_shape::RAMP_TOP));
remove_ramp_top(map, DFCoord(pos.x, pos.y, pos.z+2));
} }
} }
break; break;
@ -343,6 +354,7 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map,
if (target_type == df::tiletype::Void || target_type == tt) if (target_type == df::tiletype::Void || target_type == tt)
return false; return false;
dug_tiles.push_back(dug_tile_info(map, pos));
dig_type(map, pos, target_type); dig_type(map, pos, target_type);
// let light filter down to newly exposed tiles // let light filter down to newly exposed tiles
@ -428,12 +440,14 @@ static bool carve_tile(MapExtras::MapCache &map,
return true; return true;
} }
static bool produces_boulder(const boulder_percent_options &options, static bool produces_item(const boulder_percent_options &options,
Random::MersenneRNG &rng, MapExtras::MapCache &map, Random::MersenneRNG &rng,
df::tiletype_material tmat, const dug_tile_info &info) {
df::inclusion_type vein_type) {
uint32_t probability; uint32_t probability;
switch (vein_type) { 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::CLUSTER:
case df::inclusion_type::VEIN: case df::inclusion_type::VEIN:
probability = options.vein; probability = options.vein;
@ -446,24 +460,25 @@ static bool produces_boulder(const boulder_percent_options &options,
probability = options.layer; probability = options.layer;
break; break;
} }
}
if (tmat == df::tiletype_material::FEATURE)
probability = options.deep;
return rng.random(100) < probability; return rng.random(100) < probability;
} }
typedef std::map<std::pair<df::item_type, int32_t>, std::vector<DFCoord>>
item_coords_t;
static void do_dig(color_ostream &out, std::vector<DFCoord> &dug_coords, static void do_dig(color_ostream &out, std::vector<DFCoord> &dug_coords,
std::map<int16_t, std::vector<DFCoord>> &boulder_coords, item_coords_t &item_coords, const dig_now_options &options) {
const dig_now_options &options) {
MapExtras::MapCache map; MapExtras::MapCache map;
Random::MersenneRNG rng; Random::MersenneRNG rng;
rng.init(); rng.init();
for (uint32_t z = options.start.z; z <= options.end.z; ++z) { // go down levels instead of up so stacked ramps behave as expected
for (uint32_t y = options.start.y; y <= options.end.y; ++y) { for (int16_t z = options.end.z; z >= options.start.z; --z) {
for (uint32_t x = options.start.x; x <= options.end.x; ++x) { 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 // this will return NULL if the map block hasn't been allocated
// yet, but that means there aren't any designations anyway. // yet, but that means there aren't any designations anyway.
if (!Maps::getTileBlock(x, y, z)) if (!Maps::getTileBlock(x, y, z))
@ -473,21 +488,19 @@ static void do_dig(color_ostream &out, std::vector<DFCoord> &dug_coords,
df::tile_designation td = map.designationAt(pos); df::tile_designation td = map.designationAt(pos);
df::tile_occupancy to = map.occupancyAt(pos); df::tile_occupancy to = map.occupancyAt(pos);
if (td.bits.dig != df::tile_dig_designation::No) { if (td.bits.dig != df::tile_dig_designation::No) {
int16_t boulder_mat[2]; std::vector<dug_tile_info> dug_tiles;
memset(boulder_mat, -1, sizeof(boulder_mat)); if (dig_tile(out, map, pos, td.bits.dig, dug_tiles)) {
df::tiletype_material tmat =
tileMaterial(map.tiletypeAt(pos));
if (dig_tile(out, map, pos, td.bits.dig, boulder_mat)) {
td = map.designationAt(pos); td = map.designationAt(pos);
td.bits.dig = df::tile_dig_designation::No; td.bits.dig = df::tile_dig_designation::No;
map.setDesignationAt(pos, td); map.setDesignationAt(pos, td);
dug_coords.push_back(pos); for (auto info : dug_tiles) {
for (size_t i = 0; i < 2; ++i) { dug_coords.push_back(info.pos);
if (boulder_mat[i] < 0) if (info.imat < 0)
continue; continue;
if (produces_boulder(options.boulder_percents, rng, if (produces_item(options.boulder_percents,
tmat, map.BlockAtTile(pos)->veinTypeAt(pos))) { map, rng, info)) {
boulder_coords[boulder_mat[i]].push_back(pos); 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, static void create_boulders(color_ostream &out,
const std::map<int16_t, std::vector<DFCoord>> &boulder_coords, const item_coords_t &item_coords,
const dig_now_options &options) { const dig_now_options &options) {
df::unit *unit = world->units.active[0]; df::unit *unit = world->units.active[0];
df::historical_entity *civ = df::historical_entity::find(unit->civ_id); 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."); " option specifies an open, non-wall tile.");
} }
for (auto entry : boulder_coords) { for (auto entry : item_coords) {
df::reaction_product_itemst *prod = df::reaction_product_itemst *prod =
df::allocate<df::reaction_product_itemst>(); df::allocate<df::reaction_product_itemst>();
const std::vector<DFCoord> &coords = entry.second; const std::vector<DFCoord> &coords = entry.second;
prod->item_type = df::item_type::BOULDER; prod->item_type = entry.first.first;
prod->item_subtype = -1; prod->item_subtype = -1;
prod->mat_type = 0; prod->mat_type = 0;
prod->mat_index = entry.first; prod->mat_index = entry.first.second;
prod->probability = 100; prod->probability = 100;
prod->count = coords.size(); prod->count = coords.size();
prod->product_dimension = 1; prod->product_dimension = 1;
@ -670,13 +683,12 @@ command_result dig_now(color_ostream &out, std::vector<std::string> &params) {
return CR_FAILURE; return CR_FAILURE;
} }
// track which positions were modified and where to produce boulders of a // track which positions were modified and where to produce items
// given material
std::vector<DFCoord> dug_coords; std::vector<DFCoord> dug_coords;
std::map<int16_t, std::vector<DFCoord>> boulder_coords; item_coords_t item_coords;
do_dig(out, dug_coords, boulder_coords, options); do_dig(out, dug_coords, item_coords, options);
create_boulders(out, boulder_coords, options); create_boulders(out, item_coords, options);
unhide_dug_tiles(out, dug_coords); unhide_dug_tiles(out, dug_coords);
// force the game to recompute its walkability cache // force the game to recompute its walkability cache