2 #include "LocateResourceGoal.hpp"
4 #include "Creature.hpp"
5 #include "../world/Planet.hpp"
6 #include "../world/Resource.hpp"
7 #include "../world/Simulation.hpp"
8 #include "../world/TileType.hpp"
11 #include <glm/gtx/io.hpp>
17 Goal::Goal(Creature &c)
25 Goal::~Goal() noexcept {
28 Situation &Goal::GetSituation() noexcept {
29 return c.GetSituation();
32 const Situation &Goal::GetSituation() const noexcept {
33 return c.GetSituation();
36 Steering &Goal::GetSteering() noexcept {
37 return c.GetSteering();
40 const Steering &Goal::GetSteering() const noexcept {
41 return c.GetSteering();
44 void Goal::SetComplete() noexcept {
53 void Goal::OnComplete(std::function<void(Goal &)> cb) noexcept {
61 LocateResourceGoal::LocateResourceGoal(Creature &c, int res)
70 LocateResourceGoal::~LocateResourceGoal() noexcept {
73 std::string LocateResourceGoal::Describe() const {
74 return "locate " + GetCreature().GetSimulation().Resources()[res].name;
77 void LocateResourceGoal::Enable() {
81 void LocateResourceGoal::Tick(double dt) {
84 void LocateResourceGoal::Action() {
87 } else if (OnTargetTile()) {
89 if (!GetCreature().Moving()) {
93 GetSteering().GoTo(target_pos);
97 void LocateResourceGoal::LocateResource() {
98 if (GetSituation().OnSurface()) {
99 const world::TileType &t = GetSituation().GetTileType();
100 auto yield = t.FindResource(res);
101 if (yield != t.resources.cend()) {
103 GetSteering().Halt();
105 target_pos = GetSituation().Position();
106 target_srf = GetSituation().Surface();
107 target_tile = GetSituation().GetPlanet().SurfacePosition(target_srf, target_pos);
109 // go find somewhere else
117 void LocateResourceGoal::SearchVicinity() {
118 const world::Planet &planet = GetSituation().GetPlanet();
119 int srf = GetSituation().Surface();
120 const glm::dvec3 &pos = GetSituation().Position();
122 glm::ivec2 loc = planet.SurfacePosition(srf, pos);
123 glm::ivec2 seek_radius(2);
124 glm::ivec2 begin(glm::max(glm::ivec2(0), loc - seek_radius));
125 glm::ivec2 end(glm::min(glm::ivec2(planet.SideLength()), loc + seek_radius));
127 const world::TileType::Yield *best = nullptr;
129 double best_distance;
131 for (int y = begin.y; y < end.y; ++y) {
132 for (int x = begin.x; x < end.x; ++x) {
133 const world::TileType &type = planet.TypeAt(srf, x, y);
134 auto yield = type.FindResource(res);
135 if (yield != type.resources.cend()) {
136 double dist = glm::length2(planet.TileCenter(srf, x, y) - pos);
139 best_pos = glm::ivec2(x, y);
140 best_distance = dist;
141 } else if (yield->ubiquity - (dist * 0.125) > best->ubiquity - (best_distance * 0.125)) {
143 best_pos = glm::ivec2(x, y);
144 best_distance = dist;
151 target_pos = planet.TileCenter(srf, best_pos.x, best_pos.y);
153 target_tile = best_pos;
154 GetSteering().GoTo(target_pos);
155 std::cout << "found resource at " << target_pos << std::endl;
161 bool LocateResourceGoal::OnTargetTile() const noexcept {
162 const Situation &s = GetSituation();
164 && s.Surface() == target_srf
165 && s.GetPlanet().SurfacePosition(s.Surface(), s.Position()) == target_tile;