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));
}
// 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_tile_info> &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::pair<df::item_type, int32_t>, std::vector<DFCoord>>
item_coords_t;
static void do_dig(color_ostream &out, std::vector<DFCoord> &dug_coords,
std::map<int16_t, std::vector<DFCoord>> &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<DFCoord> &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_tile_info> 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<int16_t, std::vector<DFCoord>> &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<df::reaction_product_itemst>();
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->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<std::string> &params) {
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<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);
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