@ -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 ) {
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 ) ;
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 ;
}
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,12 +440,14 @@ 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 ) {
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 ;
@ -446,24 +460,25 @@ static bool produces_boulder(const boulder_percent_options &options,
probability = options . layer ;
break ;
}
if ( tmat = = df : : tiletype_material : : FEATURE )
probability = options . deep ;
}
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> ¶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 < 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