+ d.StandardDeviation(d.StandardDeviation() * amount);
+ }
+ }
+}
+
+namespace {
+
+std::string summarize(const Composition &comp, const app::Assets &assets) {
+ std::stringstream s;
+ bool first = true;
+ for (const auto &c : comp) {
+ if (first) {
+ first = false;
+ } else {
+ s << " or ";
+ }
+ s << assets.data.resources[c.resource].label;
+ }
+ return s.str();
+}
+
+}
+
+IngestGoal::IngestGoal(Creature &c, Creature::Stat &stat)
+: Goal(c)
+, stat(stat)
+, accept()
+, locate_subtask(nullptr)
+, ingesting(false)
+, resource(-1)
+, yield(0.0) {
+ Urgency(stat.value);
+}
+
+IngestGoal::~IngestGoal() {
+}
+
+void IngestGoal::Accept(int resource, double value) {
+ accept.Add(resource, value);
+}
+
+std::string IngestGoal::Describe() const {
+ if (resource == -1) {
+ return "ingest " + summarize(accept, Assets());
+ } else {
+ const world::Resource &r = Assets().data.resources[resource];
+ if (r.state == world::Resource::SOLID) {
+ return "eat " + r.label;
+ } else {
+ return "drink " + r.label;
+ }
+ }
+}
+
+void IngestGoal::Enable() {
+}
+
+void IngestGoal::Tick(double dt) {
+ Urgency(stat.value);
+ if (locate_subtask) {
+ locate_subtask->Urgency(Urgency() + 0.1);
+ }
+ if (ingesting) {
+ if (OnSuitableTile() && !GetSituation().Moving()) {
+ // TODO: determine satisfaction factor
+ GetCreature().Ingest(resource, yield * dt);
+ stat.Add(-1.0 * yield * dt);
+ if (stat.Empty()) {
+ SetComplete();