+
+Goal::Goal(Creature &c)
+: c(c)
+, on_complete()
+, on_foreground()
+, on_background()
+, urgency(0.0)
+, interruptible(true)
+, complete(false) {
+}
+
+Goal::~Goal() noexcept {
+}
+
+Situation &Goal::GetSituation() noexcept {
+ return c.GetSituation();
+}
+
+const Situation &Goal::GetSituation() const noexcept {
+ return c.GetSituation();
+}
+
+Steering &Goal::GetSteering() noexcept {
+ return c.GetSteering();
+}
+
+const Steering &Goal::GetSteering() const noexcept {
+ return c.GetSteering();
+}
+
+app::Assets &Goal::Assets() noexcept {
+ return c.GetSimulation().Assets();
+}
+
+const app::Assets &Goal::Assets() const noexcept {
+ return c.GetSimulation().Assets();
+}
+
+math::GaloisLFSR &Goal::Random() noexcept {
+ return Assets().random;
+}
+
+void Goal::SetComplete() {
+ if (!complete) {
+ complete = true;
+ OnComplete();
+ if (on_complete) {
+ on_complete(*this);
+ }
+ }
+}
+
+void Goal::SetForeground() {
+ OnForeground();
+ if (on_foreground) {
+ on_foreground(*this);
+ }
+}
+
+void Goal::SetBackground() {
+ OnBackground();
+ if (on_background) {
+ on_background(*this);
+ }
+}
+
+void Goal::WhenComplete(std::function<void(Goal &)> cb) noexcept {
+ on_complete = cb;
+ if (complete) {
+ on_complete(*this);
+ }
+}
+
+void Goal::WhenForeground(std::function<void(Goal &)> cb) noexcept {
+ on_foreground = cb;
+}
+
+void Goal::WhenBackground(std::function<void(Goal &)> cb) noexcept {
+ on_background = cb;
+}
+
+
+IdleGoal::IdleGoal(Creature &c)
+: Goal(c) {
+ Urgency(-1.0);
+ Interruptible(true);
+}
+
+IdleGoal::~IdleGoal() {
+}
+
+std::string IdleGoal::Describe() const {
+ return "idle";
+}
+
+void IdleGoal::Action() {
+ // use boredom as chance per minute
+ if (Random().UNorm() < GetCreature().GetStats().Boredom().value * (1.0 / 3600.0)) {
+ PickActivity();
+ }
+}
+
+void IdleGoal::PickActivity() {
+ GetCreature().AddGoal(std::unique_ptr<Goal>(new StrollGoal(GetCreature())));
+}
+
+