]> git.localhorst.tv Git - blobs.git/blob - src/creature/goal.cpp
eating and drinking
[blobs.git] / src / creature / goal.cpp
1 #include "Goal.hpp"
2 #include "LocateResourceGoal.hpp"
3
4 #include "Creature.hpp"
5 #include "../world/Planet.hpp"
6 #include "../world/TileType.hpp"
7
8 namespace blobs {
9 namespace creature {
10
11 Goal::Goal()
12 : urgency(0.0)
13 , interruptible(true)
14 , complete(false) {
15 }
16
17 Goal::~Goal() noexcept {
18 }
19
20
21 LocateResourceGoal::LocateResourceGoal(int res)
22 : res(res) {
23 }
24
25 LocateResourceGoal::~LocateResourceGoal() noexcept {
26 }
27
28 void LocateResourceGoal::Enable(Creature &c) {
29 }
30
31 void LocateResourceGoal::Tick(double dt) {
32 }
33
34 void LocateResourceGoal::Action(Creature &c) {
35         if (c.GetSituation().OnSurface()) {
36                 const world::TileType &t = c.GetSituation().GetTileType();
37                 auto yield = t.FindResource(res);
38                 if (yield != t.resources.cend()) {
39                         // hoooray
40                         c.GetSteering().Halt();
41                         Complete(true);
42                 } else {
43                         // go find somewhere else
44                         const world::Planet &planet = c.GetSituation().GetPlanet();
45                         double side_length = planet.SideLength();
46                         double offset = side_length * 0.5;
47                         glm::ivec2 loc = glm::ivec2(c.GetSituation().Position() + offset);
48                         glm::ivec2 seek_radius(2);
49                         glm::ivec2 begin(glm::max(glm::ivec2(0), loc - seek_radius));
50                         glm::ivec2 end(glm::min(glm::ivec2(side_length), loc + seek_radius));
51                         const world::TileType::Yield *best = nullptr;
52                         glm::ivec2 best_pos;
53                         double best_distance = 2 * side_length * side_length;
54                         for (int y = begin.y; y < end.y; ++y) {
55                                 for (int x = begin.x; x < end.x; ++x) {
56                                         const world::TileType &type = planet.TypeAt(c.GetSituation().Surface(), x, y);
57                                         auto yield = type.FindResource(res);
58                                         if (yield != type.resources.cend()) {
59                                                 double dist = glm::length2(glm::dvec3(x - offset + 0.5, y - offset + 0.5, 0.0) - c.GetSituation().Position());
60                                                 if (!best) {
61                                                         best = &*yield;
62                                                         best_pos = glm::ivec2(x, y);
63                                                         best_distance = dist;
64                                                 } else if (yield->ubiquity + (dist * 0.125) > best->ubiquity + (best_distance * 0.125)) {
65                                                         best = &*yield;
66                                                         best_pos = glm::ivec2(x, y);
67                                                         best_distance = dist;
68                                                 }
69                                         }
70                                 }
71                         }
72                         if (best) {
73                                 c.GetSteering().GoTo(glm::dvec3(best_pos.x - offset + 0.5, best_pos.y - offset + 0.5, 0.0));
74                         } else {
75                                 // oh crap
76                         }
77                 }
78         } else {
79                 // well, what now?
80         }
81 }
82
83 }
84 }