autofarm code cleanup (#2033)

* code cleanup on autofarm.cpp

* more code cleanup on aufofarm.cpp

* yet more cleanup of autofarm.cpp

mostly whitespace, some `*` and `&` adjustments

* downgrade autofarm to c++11

apparently the gcc we use doesn't support c++14 generic lambdas

* death to whitespace

apparently visual studio's default whitespace murderer doesn't touch `#define`s. who knew?

* Update autofarm.cpp

const is good
develop
Kelly Kinkade 2022-03-16 21:43:24 -05:00 committed by GitHub
parent ce30843b92
commit e0ecf21896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 69 additions and 94 deletions

@ -26,39 +26,33 @@
#include <queue> #include <queue>
using std::vector;
using std::string;
using std::map;
using std::set;
using std::queue;
using std::endl;
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
using df::global::world; using df::global::world;
using df::global::ui; using df::global::ui;
static command_result autofarm(color_ostream &out, vector <string> & parameters); static command_result autofarm(color_ostream& out, std::vector<std::string>& parameters);
DFHACK_PLUGIN("autofarm"); DFHACK_PLUGIN("autofarm");
DFHACK_PLUGIN_IS_ENABLED(enabled); DFHACK_PLUGIN_IS_ENABLED(enabled);
const char *tagline = "Automatically handle crop selection in farm plots based on current plant stocks."; const char* tagline = "Automatically handle crop selection in farm plots based on current plant stocks.";
const char *usage = ( const char* usage = (
"``enable autofarm``: Enables the plugin\n" "``enable autofarm``: Enables the plugin\n"
"``autofarm runonce``: Updates farm plots (one-time only)\n" "``autofarm runonce``: Updates farm plots (one-time only)\n"
"``autofarm status``: Prints status information\n" "``autofarm status``: Prints status information\n"
"``autofarm default 30``: Sets the default threshold\n" "``autofarm default 30``: Sets the default threshold\n"
"``autofarm threshold 150 helmet_plump tail_pig``: Sets thresholds\n" "``autofarm threshold 150 helmet_plump tail_pig``: Sets thresholds\n"
); );
class AutoFarm { class AutoFarm {
private: private:
map<int, int> thresholds; std::map<int, int> thresholds;
int defaultThreshold = 50; int defaultThreshold = 50;
map<int, int> lastCounts; std::map<int, int> lastCounts;
public: public:
void initialize() void initialize()
@ -106,9 +100,9 @@ public:
} }
private: private:
map<int, set<df::biome_type>> plantable_plants; std::map<int, std::set<df::biome_type>> plantable_plants;
const map<df::plant_raw_flags, df::biome_type> biomeFlagMap = { const std::map<df::plant_raw_flags, df::biome_type> biomeFlagMap = {
{ df::plant_raw_flags::BIOME_MOUNTAIN, df::biome_type::MOUNTAIN }, { 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_GLACIER, df::biome_type::GLACIER },
{ df::plant_raw_flags::BIOME_TUNDRA, df::biome_type::TUNDRA }, { df::plant_raw_flags::BIOME_TUNDRA, df::biome_type::TUNDRA },
@ -168,41 +162,37 @@ public:
{ {
plantable_plants.clear(); plantable_plants.clear();
map<int, int> counts; std::map<int, int> counts;
df::item_flags bad_flags; const uint32_t bad_flags{
bad_flags.whole = 0; #define F(x) (df::item_flags::Mask::mask_##x)
F(dump) | F(forbid) | F(garbage_collect) |
#define F(x) bad_flags.bits.x = true; F(hostile) | F(on_fire) | F(rotten) | F(trader) |
F(dump); F(forbid); F(garbage_collect); F(in_building) | F(construction) | F(artifact)
F(hostile); F(on_fire); F(rotten); F(trader);
F(in_building); F(construction); F(artifact);
#undef F #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<df::item_seedsst>(ii); auto i = virtual_cast<df::item_seedsst>(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; 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]; df::plant_raw* plant = world->raws.plants.all[ci.first];
if (is_plantable(plant)) if (is_plantable(plant))
for (auto &flagmap : biomeFlagMap) for (auto& flagmap : biomeFlagMap)
if (plant->flags.is_set(flagmap.first)) if (plant->flags.is_set(flagmap.first))
plantable_plants[plant->index].insert(flagmap.second); 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); df::plant_raw* raw = df::plant_raw::find(plant_id);
if (raw) return raw ? raw->name : "NONE";
return raw->name;
else
return "NONE";
} }
void set_farm(color_ostream& out, int new_plant_id, df::building_farmplotst* farm, int season) 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; farm->plant_id[season] = new_plant_id;
out << "autofarm: changing farm #" << farm->id << out << "autofarm: changing farm #" << farm->id <<
" from " << get_plant_name(old_plant_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<int> plants, vector<df::building_farmplotst*> farms) void set_farms(color_ostream& out, const std::set<int>& plants, const std::vector<df::building_farmplotst*>& farms)
{ {
// this algorithm attempts to change as few farms as possible, while ensuring that // 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" // 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 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 int extra = farms.size() - min * plants.size(); // the remainder that cannot be evenly divided
map<int, int> counters; std::map<int, int> counters;
counters.empty(); std::queue<df::building_farmplotst*> toChange;
queue<df::building_farmplotst*> toChange;
toChange.empty();
for (auto farm : farms) for (auto farm : farms)
{ {
int o = farm->plant_id[season]; 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 toChange.push(farm); // this farm is an excess instance for the plant it is currently planting
else else
{ {
@ -281,44 +268,33 @@ public:
lastCounts.clear(); lastCounts.clear();
df::item_flags bad_flags; const uint32_t bad_flags{
bad_flags.whole = 0; #define F(x) (df::item_flags::Mask::mask_##x)
F(dump) | F(forbid) | F(garbage_collect) |
#define F(x) bad_flags.bits.x = true; F(hostile) | F(on_fire) | F(rotten) | F(trader) |
F(dump); F(forbid); F(garbage_collect); F(in_building) | F(construction) | F(artifact)
F(hostile); F(on_fire); F(rotten); F(trader); #undef F
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 // 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 count = [&, this](df::item* i) {
{ auto mat = i->getMaterialIndex();
auto i = virtual_cast<df::item_plantst>(ii); if ((i->flags.whole & bad_flags) == 0 &&
if (i && plantable_plants.count(mat) > 0)
(i->flags.whole & bad_flags.whole) == 0 &&
plantable_plants.count(i->mat_index) > 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<df::item_plant_growthst>(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<df::biome_type, set<int>> plants; std::map<df::biome_type, std::set<int>> plants;
plants.clear();
for (auto &plantable : plantable_plants) for (auto& plantable : plantable_plants)
{ {
df::plant_raw* plant = world->raws.plants.all[plantable.first]; df::plant_raw* plant = world->raws.plants.all[plantable.first];
if (lastCounts[plant->index] < getThreshold(plant->index)) if (lastCounts[plant->index] < getThreshold(plant->index))
@ -328,10 +304,9 @@ public:
} }
} }
map<df::biome_type, vector<df::building_farmplotst*>> farms; std::map<df::biome_type, std::vector<df::building_farmplotst*>> farms;
farms.clear();
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<df::building_farmplotst>(bb); auto farm = virtual_cast<df::building_farmplotst>(bb);
if (farm->flags.bits.exists) 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); set_farms(out, plants[ff.first], ff.second);
} }
@ -355,28 +330,28 @@ public:
void status(color_ostream& out) void status(color_ostream& out)
{ {
out << (enabled ? "Running." : "Stopped.") << endl; out << (enabled ? "Running." : "Stopped.") << '\n';
for (auto &lc : lastCounts) for (auto& lc : lastCounts)
{ {
auto plant = world->raws.plants.all[lc.first]; 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) if (lastCounts[th.first] > 0)
continue; continue;
auto plant = world->raws.plants.all[th.first]; 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<AutoFarm> autofarmInstance; static std::unique_ptr<AutoFarm> autofarmInstance;
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init(color_ostream& out, std::vector <PluginCommand>& commands)
{ {
if (world && ui) { if (world && ui) {
commands.push_back( commands.push_back(
@ -389,14 +364,14 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( color_ostream &out ) DFhackCExport command_result plugin_shutdown(color_ostream& out)
{ {
autofarmInstance.release(); autofarmInstance.release();
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate(color_ostream &out) DFhackCExport command_result plugin_onupdate(color_ostream& out)
{ {
if (!autofarmInstance) if (!autofarmInstance)
return CR_OK; return CR_OK;
@ -418,19 +393,19 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) DFhackCExport command_result plugin_enable(color_ostream& out, bool enable)
{ {
enabled = enable; enabled = enable;
return CR_OK; return CR_OK;
} }
static command_result setThresholds(color_ostream& out, vector<string> & parameters) static command_result setThresholds(color_ostream& out, std::vector<std::string>& parameters)
{ {
int val = atoi(parameters[1].c_str()); int val = atoi(parameters[1].c_str());
for (size_t i = 2; i < parameters.size(); i++) for (size_t i = 2; i < parameters.size(); i++)
{ {
string id = parameters[i]; std::string id = parameters[i];
transform(id.begin(), id.end(), id.begin(), ::toupper); std::transform(id.begin(), id.end(), id.begin(), ::toupper);
bool ok = false; bool ok = false;
for (auto plant : world->raws.plants.all) for (auto plant : world->raws.plants.all)
@ -444,14 +419,14 @@ static command_result setThresholds(color_ostream& out, vector<string> & paramet
} }
if (!ok) if (!ok)
{ {
out << "Cannot find plant with id " << id << endl; out << "Cannot find plant with id " << id << '\n';
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
} }
return CR_OK; return CR_OK;
} }
static command_result autofarm(color_ostream &out, vector <string> & parameters) static command_result autofarm(color_ostream& out, std::vector<std::string>& parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;