, font_path(path + "fonts/")
, skin_path(path + "skins/")
, tile_path(path + "tiles/")
-, random(0)
+, random(0x6283B64CEFE47925)
, fonts{
graphics::Font(font_path + "DejaVuSans.ttf", 32),
graphics::Font(font_path + "DejaVuSans.ttf", 24),
// sunset
//.FirstPerson(3, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
// from afar
- .MapView(0, glm::vec3(0.0f, 0.0f, 10.0f), 0.0f)
+ .MapView(0, glm::vec3(0.0f, 0.0f, 15.0f), 0.0f)
// from afar, rotating
//.Orbital(glm::vec3(-60.0f, 0.0f, 0.0f))
;
glm::dvec3 target_pos;
int target_srf;
glm::ivec2 target_tile;
+ bool searching;
};
bool OnSurface() const noexcept;
int Surface() const noexcept { return surface; }
const glm::dvec3 &Position() const noexcept { return position; }
+ bool OnTile() const noexcept;
+ glm::ivec2 SurfacePosition() const noexcept;
world::Tile &GetTile() const noexcept;
const world::TileType &GetTileType() const noexcept;
void Creature::Hurt(double dt) noexcept {
health = std::max(0.0, health - dt);
if (health == 0.0) {
+ std::cout << "[" << int(sim.Time()) << "s] "
+ << name << " died" << std::endl;
Die();
}
}
situation.Move(vel * dt);
vel += acc * dt;
+ if (Age() > properties.death_age) {
+ std::cout << "[" << int(sim.Time()) << "s] "
+ << name << " died of old age" << std::endl;
+ }
+
for (auto &need : needs) {
need->Tick(dt);
}
return type == PLANET_SURFACE;
}
+bool Situation::OnTile() const noexcept {
+ glm::ivec2 t(planet->SurfacePosition(surface, position));
+ return type == PLANET_SURFACE
+ && t.x >= 0 && t.x < planet->SideLength()
+ && t.y >= 0 && t.y < planet->SideLength();
+}
+
+glm::ivec2 Situation::SurfacePosition() const noexcept {
+ return planet->SurfacePosition(surface, position);
+}
+
world::Tile &Situation::GetTile() const noexcept {
- double side_length = planet->SideLength();
- double offset = side_length * 0.5;
- double x = std::max(0.0, std::min(side_length, position.x + offset));
- double y = std::max(0.0, std::min(side_length, position.y + offset));
- return planet->TileAt(surface, int(x), int(y));
+ glm::ivec2 t(planet->SurfacePosition(surface, position));
+ return planet->TileAt(surface, t.x, t.y);
}
const world::TileType &Situation::GetTileType() const noexcept {
- return planet->GetSimulation().TileTypes()[GetTile().type];
+ glm::ivec2 t(planet->SurfacePosition(surface, position));
+ return planet->TypeAt(surface, t.x, t.y);
}
void Situation::Move(const glm::dvec3 &dp) noexcept {
, found(false)
, target_pos(0.0)
, target_srf(0)
-, target_tile(0) {
+, target_tile(0)
+, searching(false) {
}
LocateResourceGoal::~LocateResourceGoal() noexcept {
void LocateResourceGoal::Action() {
if (!found) {
- LocateResource();
+ if (!searching) {
+ LocateResource();
+ } else {
+ double dist = glm::length2(GetSituation().Position() - target_pos);
+ if (dist < 0.0001) {
+ GetSteering().Halt();
+ searching = false;
+ } else {
+ GetSteering().GoTo(target_pos);
+ }
+ }
} else if (OnTargetTile()) {
GetSteering().Halt();
if (!GetCreature().Moving()) {
// hoooray
GetSteering().Halt();
found = true;
+ searching = false;
target_pos = GetSituation().Position();
target_srf = GetSituation().Surface();
target_tile = GetSituation().GetPlanet().SurfacePosition(target_srf, target_pos);
glm::ivec2 loc = planet.SurfacePosition(srf, pos);
glm::ivec2 seek_radius(2);
glm::ivec2 begin(glm::max(glm::ivec2(0), loc - seek_radius));
- glm::ivec2 end(glm::min(glm::ivec2(planet.SideLength()), loc + seek_radius));
+ glm::ivec2 end(glm::min(glm::ivec2(planet.SideLength() - 1), loc + seek_radius));
const world::TileType::Yield *best = nullptr;
glm::ivec2 best_pos;
double best_distance;
- for (int y = begin.y; y < end.y; ++y) {
- for (int x = begin.x; x < end.x; ++x) {
+ for (int y = begin.y; y <= end.y; ++y) {
+ for (int x = begin.x; x <= end.x; ++x) {
const world::TileType &type = planet.TypeAt(srf, x, y);
auto yield = type.FindResource(res);
if (yield != type.resources.cend()) {
}
if (best) {
found = true;
+ searching = false;
target_pos = planet.TileCenter(srf, best_pos.x, best_pos.y);
target_srf = srf;
target_tile = best_pos;
GetSteering().GoTo(target_pos);
- } else {
- // oh crap
+ } else if (!searching) {
+ found = false;
+ searching = true;
+ target_pos = GetSituation().Position();
+ target_pos[(srf + 0) % 3] += Assets().random.SNorm();
+ target_pos[(srf + 1) % 3] += Assets().random.SNorm();
+ GetSteering().GoTo(target_pos);
}
}
const Situation &s = GetSituation();
return s.OnSurface()
&& s.Surface() == target_srf
- && s.GetPlanet().SurfacePosition(s.Surface(), s.Position()) == target_tile;
+ && s.OnTile()
+ && s.SurfacePosition() == target_tile;
}
}
}
double SNorm() noexcept {
- return 2.0 * UNorm() - 1.0;
+ return (2.0 * UNorm()) - 1.0;
}
double UNorm() noexcept {
- return double(Next<std::uint64_t>()) * (1.0 / double(std::numeric_limits<std::uint64_t>::max()));
+ return double(Next<std::uint64_t>()) / double(std::numeric_limits<std::uint64_t>::max());
}
template<class Container>
Label *name;
Label *age;
Label *mass;
+ Label *pos;
+ Label *tile;
Label *goal;
Panel *needs;
Panel panel;
, name(new Label(assets.fonts.large))
, age(new Label(assets.fonts.medium))
, mass(new Label(assets.fonts.medium))
+, pos(new Label(assets.fonts.medium))
+, tile(new Label(assets.fonts.medium))
, goal(new Label(assets.fonts.medium))
, needs(new Panel)
, panel()
->Spacing(10.0f)
->Direction(Panel::HORIZONTAL);
+ age->Text("0000s");
Label *age_label = new Label(assets.fonts.medium);
age_label->Text("Age");
Panel *age_panel = new Panel;
->Spacing(10.0f)
->Direction(Panel::HORIZONTAL);
+ mass->Text("00.000kg");
Label *mass_label = new Label(assets.fonts.medium);
mass_label->Text("Mass");
Panel *mass_panel = new Panel;
->Spacing(10.0f)
->Direction(Panel::HORIZONTAL);
+ pos->Text("<00.0, 00.0, 00.0>");
+ Label *pos_label = new Label(assets.fonts.medium);
+ pos_label->Text("Pos");
+ Panel *pos_panel = new Panel;
+ pos_panel
+ ->Add(pos_label)
+ ->Add(pos)
+ ->Spacing(10.0f)
+ ->Direction(Panel::HORIZONTAL);
+
+ tile->Text("<00, 00> (mountains)");
+ Label *tile_label = new Label(assets.fonts.medium);
+ tile_label->Text("Tile");
+ Panel *tile_panel = new Panel;
+ tile_panel
+ ->Add(tile_label)
+ ->Add(tile)
+ ->Spacing(10.0f)
+ ->Direction(Panel::HORIZONTAL);
+
+ goal->Text("long goal description");
Label *goal_label = new Label(assets.fonts.medium);
goal_label->Text("Goal");
Panel *goal_panel = new Panel;
.Add(name)
->Add(age_panel)
->Add(mass_panel)
+ ->Add(pos_panel)
+ ->Add(tile_panel)
->Add(goal_panel)
->Add(health_panel)
->Add(needs)
ss << std::fixed << std::setprecision(3) << c->Mass() << "kg";
mass->Text(ss.str());
}
+ {
+ const glm::dvec3 &p = c->GetSituation().Position();
+ std::stringstream ss;
+ ss << std::fixed << std::setprecision(1)
+ << "<" << p.x << ", " << p.y << ", " << p.z << ">";
+ pos->Text(ss.str());
+ }
+ {
+ glm::ivec2 t = c->GetSituation().SurfacePosition();
+ std::stringstream ss;
+ ss << std::fixed << std::setprecision(1)
+ << "<" << t.x << ", " << t.y
+ << "> (" << c->GetSituation().GetTileType().label << ")";
+ tile->Text(ss.str());
+ }
if (c->Goals().empty()) {
goal->Text("none");
} else {