# scan the map for ore veins target_ore = $script_args[0] def find_all_ore_veins puts 'scanning map...' $ore_veins = {} seen_mat = {} df.each_map_block { |block| block.block_events.grep(DFHack::BlockSquareEventMineralst).each { |vein| mat_index = vein.inorganic_mat if not seen_mat[mat_index] or $ore_veins[mat_index] seen_mat[mat_index] = true if df.world.raws.inorganics[mat_index].flags[:METAL_ORE] $ore_veins[mat_index] ||= [] $ore_veins[mat_index] << [block.map_pos.x, block.map_pos.y, block.map_pos.z] end end } } df.onstatechange_register_once { |st| if st == :MAP_LOADED $ore_veins = nil # invalidate veins cache true end } $ore_veins end $ore_veins ||= find_all_ore_veins if not target_ore or target_ore == 'help' puts <<EOS Scan the map to find one random tile of unmined ore. It will center the game view on that tile and mark it for digging. Only works with metal ores. Usage: locate_ore list list all existing vein materials (including mined ones) locate_ore hematite find one tile of unmined hematite ore locate_ore iron find one tile of unmined ore you can smelt into iron EOS elsif target_ore and mats = $ore_veins.keys.find_all { |k| ino = df.world.raws.inorganics[k] ino.id =~ /#{target_ore}/i or ino.metal_ore.mat_index.find { |m| df.world.raws.inorganics[m].id =~ /#{target_ore}/i } } and not mats.empty? pos = nil dxs = (0..15).sort_by { rand } dys = (0..15).sort_by { rand } if found_mat = mats.sort_by { rand }.find { |mat| $ore_veins[mat].sort_by { rand }.find { |bx, by, bz| dys.find { |dy| dxs.find { |dx| tile = df.map_tile_at(bx+dx, by+dy, bz) if tile.tilemat == :MINERAL and tile.designation.dig == :No and tile.shape == :WALL and tile.mat_index_vein == mat and # ignore map borders bx+dx > 0 and bx+dx < df.world.map.x_count-1 and by+dy > 0 and by+dy < df.world.map.y_count-1 pos = [bx+dx, by+dy, bz] end } } } } df.center_viewscreen(*pos) df.map_tile_at(*pos).dig puts "Here is some #{df.world.raws.inorganics[found_mat].id}" else puts "Cannot find unmined #{mats.map { |mat| df.world.raws.inorganics[mat].id }.join(', ')}" end else puts "Available ores:", $ore_veins.sort_by { |mat, pos| pos.length }.map { |mat, pos| ore = df.world.raws.inorganics[mat] metals = ore.metal_ore.mat_index.map { |m| df.world.raws.inorganics[m] } ' ' + ore.id.downcase + ' (' + metals.map { |m| m.id.downcase }.join(', ') + ')' } end