fix autofarm berry problem

Update autofarm to count PLANT_GROWTHS as well as PLANTS for threshold purposes. This addresses #1902.

Also addresses some pointer hygiene issues in autofarm.
develop
Kelly Kinkade 2021-08-07 15:32:43 -05:00
parent 8b14fbe544
commit ce50bbdfde
1 changed files with 42 additions and 19 deletions

@ -12,6 +12,8 @@
#include "df/global_objects.h" #include "df/global_objects.h"
#include "df/item.h" #include "df/item.h"
#include "df/item_plantst.h" #include "df/item_plantst.h"
#include "df/item_plant_growthst.h"
#include "df/item_seedsst.h"
#include "df/items_other_id.h" #include "df/items_other_id.h"
#include "df/unit.h" #include "df/unit.h"
#include "df/building.h" #include "df/building.h"
@ -179,18 +181,18 @@ public:
for (auto ii : world->items.other[df::items_other_id::SEEDS]) for (auto ii : world->items.other[df::items_other_id::SEEDS])
{ {
df::item_plantst* i = (df::item_plantst*)ii; auto i = virtual_cast<df::item_seedsst>(ii);
if ((i->flags.whole & bad_flags.whole) == 0) if (i && (i->flags.whole & bad_flags.whole) == 0)
counts[i->mat_index] += i->stack_size; counts[i->mat_index] += i->stack_size;
} }
for (auto ci : counts) for (auto &ci : counts)
{ {
if (df::global::ui->tasks.discovered_plants[ci.first]) if (df::global::ui->tasks.discovered_plants[ci.first])
{ {
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);
} }
@ -222,9 +224,9 @@ public:
{ {
// 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"
int season = *df::global::cur_season; int season = *df::global::cur_season;
if (farms.empty() || plants.empty()) if (farms.empty() || plants.empty())
{ {
// if no more plants were requested, fallow all farms // if no more plants were requested, fallow all farms
@ -291,20 +293,35 @@ public:
F(in_building); F(construction); F(artifact); F(in_building); F(construction); F(artifact);
#undef F #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]) for (auto ii : world->items.other[df::items_other_id::PLANT])
{ {
df::item_plantst* i = (df::item_plantst*)ii; auto i = virtual_cast<df::item_plantst>(ii);
if ((i->flags.whole & bad_flags.whole) == 0 && 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 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) plantable_plants.count(i->mat_index) > 0)
{ {
lastCounts[i->mat_index] += i->stack_size; lastCounts[i->mat_index] += i->stack_size;
} }
} }
map<df::biome_type, set<int>> plants; map<df::biome_type, set<int>> plants;
plants.clear(); 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))
@ -319,7 +336,7 @@ public:
for (auto bb : world->buildings.other[df::buildings_other_id::FARM_PLOT]) for (auto bb : world->buildings.other[df::buildings_other_id::FARM_PLOT])
{ {
df::building_farmplotst* farm = (df::building_farmplotst*) bb; auto farm = virtual_cast<df::building_farmplotst>(bb);
if (farm->flags.bits.exists) if (farm->flags.bits.exists)
{ {
df::biome_type biome; df::biome_type biome;
@ -333,7 +350,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);
} }
@ -342,13 +359,13 @@ public:
void status(color_ostream& out) void status(color_ostream& out)
{ {
out << (enabled ? "Running." : "Stopped.") << endl; out << (enabled ? "Running." : "Stopped.") << endl;
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 << endl;
} }
for (auto th : thresholds) for (auto &th : thresholds)
{ {
if (lastCounts[th.first] > 0) if (lastCounts[th.first] > 0)
continue; continue;
@ -359,7 +376,7 @@ public:
} }
}; };
static 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)
@ -371,13 +388,13 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
) )
); );
} }
autofarmInstance = new AutoFarm(); autofarmInstance = std::move(std::make_unique<AutoFarm>());
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( color_ostream &out ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
delete autofarmInstance; autofarmInstance.release();
return CR_OK; return CR_OK;
} }
@ -442,15 +459,21 @@ static command_result autofarm(color_ostream &out, vector <string> & parameters)
CoreSuspender suspend; CoreSuspender suspend;
if (parameters.size() == 1 && parameters[0] == "runonce") if (parameters.size() == 1 && parameters[0] == "runonce")
autofarmInstance->process(out); {
if (autofarmInstance) autofarmInstance->process(out);
}
else if (parameters.size() == 1 && parameters[0] == "enable") else if (parameters.size() == 1 && parameters[0] == "enable")
plugin_enable(out, true); plugin_enable(out, true);
else if (parameters.size() == 1 && parameters[0] == "disable") else if (parameters.size() == 1 && parameters[0] == "disable")
plugin_enable(out, false); plugin_enable(out, false);
else if (parameters.size() == 2 && parameters[0] == "default") else if (parameters.size() == 2 && parameters[0] == "default")
autofarmInstance->setDefault(atoi(parameters[1].c_str())); {
if (autofarmInstance) autofarmInstance->setDefault(atoi(parameters[1].c_str()));
}
else if (parameters.size() >= 3 && parameters[0] == "threshold") else if (parameters.size() >= 3 && parameters[0] == "threshold")
return setThresholds(out, parameters); {
if (autofarmInstance) return setThresholds(out, parameters);
}
else if (parameters.size() == 0 || (parameters.size() == 1 && parameters[0] == "status")) else if (parameters.size() == 0 || (parameters.size() == 1 && parameters[0] == "status"))
autofarmInstance->status(out); autofarmInstance->status(out);
else else