Files
voxelforge/core/src/Behavior.cpp
T

156 lines
5.2 KiB
C++

#include "vf/Behavior.h"
#include <algorithm>
#include <cmath>
#include <utility>
namespace vf {
namespace {
constexpr int shadeProbeHeight = 8;
bool cellIsShaded(const World& world, const Vec3i& cell) {
for (int y = cell.y + 1; y <= cell.y + shadeProbeHeight; ++y) {
if (world.solidAt(cell.x, y, cell.z)) return true;
}
return false;
}
Vec3 horizontalHeading(uint32_t& rng) {
float angle = behaviorUnitFloat(rng) * 6.2831853f;
return {std::cos(angle), 0.0f, std::sin(angle)};
}
const SpeciesStats& statsOf(const BehaviorContext& ctx) {
return speciesStats(ctx.agent->species);
}
std::unique_ptr<BehaviorNode> condition(const char* name, BehaviorPredicate predicate) {
return std::unique_ptr<BehaviorNode>(new ConditionNode(name, std::move(predicate)));
}
std::unique_ptr<BehaviorNode> action(const char* name, BehaviorAction fn) {
return std::unique_ptr<BehaviorNode>(new ActionNode(name, std::move(fn)));
}
BehaviorStatus followRouteAction(BehaviorContext& ctx) { return followRouteStep(ctx); }
} // namespace
const char* behaviorStatusName(BehaviorStatus status) {
switch (status) {
case BehaviorStatus::Failure: return "failure";
case BehaviorStatus::Success: return "success";
case BehaviorStatus::Running: return "running";
}
return "unknown";
}
uint32_t behaviorNextRandom(uint32_t& state) {
if (state == 0u) state = 0x9e3779b9u;
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
return state;
}
float behaviorUnitFloat(uint32_t& state) {
return static_cast<float>(behaviorNextRandom(state)) / 4294967296.0f;
}
int behaviorRandomRange(uint32_t& state, int minInclusive, int maxInclusive) {
if (maxInclusive <= minInclusive) return minInclusive;
uint32_t span = static_cast<uint32_t>(maxInclusive - minInclusive + 1);
return minInclusive + static_cast<int>(behaviorNextRandom(state) % span);
}
Vec3i behaviorCellOf(const Vec3& position) {
return {static_cast<int>(std::floor(position.x)), static_cast<int>(std::floor(position.y)),
static_cast<int>(std::floor(position.z))};
}
Vec3 behaviorCellCenter(const Vec3i& cell) {
return {static_cast<float>(cell.x) + 0.5f, static_cast<float>(cell.y),
static_cast<float>(cell.z) + 0.5f};
}
float behaviorHorizontalDistance(const Vec3& a, const Vec3& b) {
float dx = a.x - b.x;
float dz = a.z - b.z;
return std::sqrt(dx * dx + dz * dz);
}
void Blackboard::setNumber(const std::string& key, float value) { numbers[key] = value; }
void Blackboard::setCount(const std::string& key, int value) { counts[key] = value; }
void Blackboard::setFlag(const std::string& key, bool value) { flags[key] = value; }
void Blackboard::setPoint(const std::string& key, const Vec3& value) { points[key] = value; }
void Blackboard::setCell(const std::string& key, const Vec3i& value) { cells[key] = value; }
void Blackboard::setRoute(const std::string& key, std::vector<Vec3i> cellList) {
routes[key] = std::move(cellList);
}
bool Blackboard::hasNumber(const std::string& key) const { return numbers.count(key) != 0; }
bool Blackboard::hasCount(const std::string& key) const { return counts.count(key) != 0; }
bool Blackboard::hasFlag(const std::string& key) const { return flags.count(key) != 0; }
bool Blackboard::hasPoint(const std::string& key) const { return points.count(key) != 0; }
bool Blackboard::hasCell(const std::string& key) const { return cells.count(key) != 0; }
bool Blackboard::hasRoute(const std::string& key) const { return routes.count(key) != 0; }
float Blackboard::number(const std::string& key, float fallback) const {
auto found = numbers.find(key);
return found == numbers.end() ? fallback : found->second;
}
int Blackboard::count(const std::string& key, int fallback) const {
auto found = counts.find(key);
return found == counts.end() ? fallback : found->second;
}
bool Blackboard::flag(const std::string& key, bool fallback) const {
auto found = flags.find(key);
return found == flags.end() ? fallback : found->second;
}
Vec3 Blackboard::point(const std::string& key, const Vec3& fallback) const {
auto found = points.find(key);
return found == points.end() ? fallback : found->second;
}
Vec3i Blackboard::cell(const std::string& key, const Vec3i& fallback) const {
auto found = cells.find(key);
return found == cells.end() ? fallback : found->second;
}
const std::vector<Vec3i>* Blackboard::route(const std::string& key) const {
auto found = routes.find(key);
return found == routes.end() ? nullptr : &found->second;
}
void Blackboard::eraseNumber(const std::string& key) { numbers.erase(key); }
void Blackboard::eraseRoute(const std::string& key) { routes.erase(key); }
void Blackboard::clear() {
numbers.clear();
counts.clear();
flags.clear();
points.clear();
cells.clear();
routes.clear();
}
std::size_t Blackboard::entryCount() const {
return numbers.size() + counts.size() + flags.size() + points.size() + cells.size() +
routes.size();
}
BehaviorNode::BehaviorNode(std::string name) : nodeName(std::move(name)) {}
BehaviorNode::~BehaviorNode() = default;
BehaviorNode* BehaviorNode::childAt(int index) const {
(void)index;
return nullptr;
}