diff --git a/plugins/autofarm.cpp b/plugins/autofarm.cpp index f0aeaead0..b9414970c 100644 --- a/plugins/autofarm.cpp +++ b/plugins/autofarm.cpp @@ -26,39 +26,33 @@ #include -using std::vector; -using std::string; -using std::map; -using std::set; -using std::queue; -using std::endl; using namespace DFHack; using namespace df::enums; using df::global::world; using df::global::ui; -static command_result autofarm(color_ostream &out, vector & parameters); +static command_result autofarm(color_ostream& out, std::vector& parameters); DFHACK_PLUGIN("autofarm"); DFHACK_PLUGIN_IS_ENABLED(enabled); -const char *tagline = "Automatically handle crop selection in farm plots based on current plant stocks."; -const char *usage = ( - "``enable autofarm``: Enables the plugin\n" - "``autofarm runonce``: Updates farm plots (one-time only)\n" - "``autofarm status``: Prints status information\n" - "``autofarm default 30``: Sets the default threshold\n" - "``autofarm threshold 150 helmet_plump tail_pig``: Sets thresholds\n" - ); +const char* tagline = "Automatically handle crop selection in farm plots based on current plant stocks."; +const char* usage = ( + "``enable autofarm``: Enables the plugin\n" + "``autofarm runonce``: Updates farm plots (one-time only)\n" + "``autofarm status``: Prints status information\n" + "``autofarm default 30``: Sets the default threshold\n" + "``autofarm threshold 150 helmet_plump tail_pig``: Sets thresholds\n" + ); class AutoFarm { private: - map thresholds; + std::map thresholds; int defaultThreshold = 50; - map lastCounts; + std::map lastCounts; public: void initialize() @@ -106,9 +100,9 @@ public: } private: - map> plantable_plants; + std::map> plantable_plants; - const map biomeFlagMap = { + const std::map biomeFlagMap = { { df::plant_raw_flags::BIOME_MOUNTAIN, df::biome_type::MOUNTAIN }, { df::plant_raw_flags::BIOME_GLACIER, df::biome_type::GLACIER }, { df::plant_raw_flags::BIOME_TUNDRA, df::biome_type::TUNDRA }, @@ -168,41 +162,37 @@ public: { plantable_plants.clear(); - map counts; + std::map counts; - df::item_flags bad_flags; - bad_flags.whole = 0; - -#define F(x) bad_flags.bits.x = true; - F(dump); F(forbid); F(garbage_collect); - F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact); + const uint32_t bad_flags{ +#define F(x) (df::item_flags::Mask::mask_##x) + F(dump) | F(forbid) | F(garbage_collect) | + F(hostile) | F(on_fire) | F(rotten) | F(trader) | + F(in_building) | F(construction) | F(artifact) #undef F + }; - for (auto ii : world->items.other[df::items_other_id::SEEDS]) + for (auto& ii : world->items.other[df::items_other_id::SEEDS]) { auto i = virtual_cast(ii); - if (i && (i->flags.whole & bad_flags.whole) == 0) + if (i && (i->flags.whole & bad_flags) == 0) counts[i->mat_index] += i->stack_size; } - for (auto &ci : counts) + for (auto& ci : counts) { df::plant_raw* plant = world->raws.plants.all[ci.first]; if (is_plantable(plant)) - for (auto &flagmap : biomeFlagMap) + for (auto& flagmap : biomeFlagMap) if (plant->flags.is_set(flagmap.first)) plantable_plants[plant->index].insert(flagmap.second); } } - string get_plant_name(int plant_id) + std::string get_plant_name(int plant_id) { - df::plant_raw *raw = df::plant_raw::find(plant_id); - if (raw) - return raw->name; - else - return "NONE"; + df::plant_raw* raw = df::plant_raw::find(plant_id); + return raw ? raw->name : "NONE"; } void set_farm(color_ostream& out, int new_plant_id, df::building_farmplotst* farm, int season) @@ -213,11 +203,11 @@ public: farm->plant_id[season] = new_plant_id; out << "autofarm: changing farm #" << farm->id << " from " << get_plant_name(old_plant_id) << - " to " << get_plant_name(new_plant_id) << endl; + " to " << get_plant_name(new_plant_id) << '\n'; } } - void set_farms(color_ostream& out, set plants, vector farms) + void set_farms(color_ostream& out, const std::set& plants, const std::vector& farms) { // this algorithm attempts to change as few farms as possible, while ensuring that // the number of farms planting each eligible plant is "as equal as possible" @@ -238,16 +228,13 @@ public: int min = farms.size() / plants.size(); // the number of farms that should plant each eligible plant, rounded down int extra = farms.size() - min * plants.size(); // the remainder that cannot be evenly divided - map counters; - counters.empty(); - - queue toChange; - toChange.empty(); + std::map counters; + std::queue toChange; for (auto farm : farms) { int o = farm->plant_id[season]; - if (plants.count(o)==0 || counters[o] > min || (counters[o] == min && extra == 0)) + if (plants.count(o) == 0 || counters[o] > min || (counters[o] == min && extra == 0)) toChange.push(farm); // this farm is an excess instance for the plant it is currently planting else { @@ -281,44 +268,33 @@ public: lastCounts.clear(); - df::item_flags bad_flags; - bad_flags.whole = 0; - -#define F(x) bad_flags.bits.x = true; - F(dump); F(forbid); F(garbage_collect); - F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact); -#undef F + const uint32_t bad_flags{ + #define F(x) (df::item_flags::Mask::mask_##x) + F(dump) | F(forbid) | F(garbage_collect) | + F(hostile) | F(on_fire) | F(rotten) | F(trader) | + F(in_building) | F(construction) | F(artifact) + #undef F + }; // have to scan both items[PLANT] and items[PLANT_GROWTH] because agricultural products can be either - for (auto ii : world->items.other[df::items_other_id::PLANT]) - { - auto i = virtual_cast(ii); - if (i && - (i->flags.whole & bad_flags.whole) == 0 && - plantable_plants.count(i->mat_index) > 0) + auto count = [&, this](df::item* i) { + auto mat = i->getMaterialIndex(); + if ((i->flags.whole & bad_flags) == 0 && + plantable_plants.count(mat) > 0) { - lastCounts[i->mat_index] += i->stack_size; + lastCounts[mat] += i->getStackSize(); } - } - - for (auto ii : world->items.other[df::items_other_id::PLANT_GROWTH]) - { - auto i = virtual_cast(ii); - if (i && - (i->flags.whole & bad_flags.whole) == 0 && - plantable_plants.count(i->mat_index) > 0) - { - lastCounts[i->mat_index] += i->stack_size; - } - } + }; + for (auto i : world->items.other[df::items_other_id::PLANT]) + count(i); + for (auto i : world->items.other[df::items_other_id::PLANT_GROWTH]) + count(i); - map> plants; - plants.clear(); + std::map> plants; - for (auto &plantable : plantable_plants) + for (auto& plantable : plantable_plants) { df::plant_raw* plant = world->raws.plants.all[plantable.first]; if (lastCounts[plant->index] < getThreshold(plant->index)) @@ -328,10 +304,9 @@ public: } } - map> farms; - farms.clear(); + std::map> farms; - for (auto bb : world->buildings.other[df::buildings_other_id::FARM_PLOT]) + for (auto& bb : world->buildings.other[df::buildings_other_id::FARM_PLOT]) { auto farm = virtual_cast(bb); if (farm->flags.bits.exists) @@ -347,7 +322,7 @@ public: } } - for (auto &ff : farms) + for (auto& ff : farms) { set_farms(out, plants[ff.first], ff.second); } @@ -355,28 +330,28 @@ public: void status(color_ostream& out) { - out << (enabled ? "Running." : "Stopped.") << endl; - for (auto &lc : lastCounts) + out << (enabled ? "Running." : "Stopped.") << '\n'; + for (auto& lc : lastCounts) { auto plant = world->raws.plants.all[lc.first]; - out << plant->id << " limit " << getThreshold(lc.first) << " current " << lc.second << endl; + out << plant->id << " limit " << getThreshold(lc.first) << " current " << lc.second << '\n'; } - for (auto &th : thresholds) + for (auto& th : thresholds) { if (lastCounts[th.first] > 0) continue; auto plant = world->raws.plants.all[th.first]; - out << plant->id << " limit " << getThreshold(th.first) << " current 0" << endl; + out << plant->id << " limit " << getThreshold(th.first) << " current 0" << '\n'; } - out << "Default: " << defaultThreshold << endl; + out << "Default: " << defaultThreshold << '\n'; } }; static std::unique_ptr autofarmInstance; -DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +DFhackCExport command_result plugin_init(color_ostream& out, std::vector & commands) { if (world && ui) { commands.push_back( @@ -389,14 +364,14 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector & parameters) +static command_result setThresholds(color_ostream& out, std::vector& parameters) { int val = atoi(parameters[1].c_str()); for (size_t i = 2; i < parameters.size(); i++) { - string id = parameters[i]; - transform(id.begin(), id.end(), id.begin(), ::toupper); + std::string id = parameters[i]; + std::transform(id.begin(), id.end(), id.begin(), ::toupper); bool ok = false; for (auto plant : world->raws.plants.all) @@ -444,14 +419,14 @@ static command_result setThresholds(color_ostream& out, vector & paramet } if (!ok) { - out << "Cannot find plant with id " << id << endl; + out << "Cannot find plant with id " << id << '\n'; return CR_WRONG_USAGE; } } return CR_OK; } -static command_result autofarm(color_ostream &out, vector & parameters) +static command_result autofarm(color_ostream& out, std::vector& parameters) { CoreSuspender suspend;