Initial code findings

This commit is contained in:
churl
2022-05-14 23:30:58 +02:00
parent e939bce35c
commit 725c69e54a
11 changed files with 56 additions and 50 deletions

View File

@ -1,10 +1,6 @@
#include "ant.hpp" #include "ant.hpp"
#include "pheromone_map.hpp"
#include <cmath>
#include <iostream>
#include <numbers>
#include <random>
// TODO: Should every ant have its own random generators? Why not initialize with coordinates and put the random numbers in there (from main)
Ant::Ant(PheromoneMap& pheromones, double x, double y) Ant::Ant(PheromoneMap& pheromones, double x, double y)
: WorldObject(x, y, 3, sf::Color::Black), pheromones(pheromones) { : WorldObject(x, y, 3, sf::Color::Black), pheromones(pheromones) {
std::random_device rd; // obtain a random number from hardware std::random_device rd; // obtain a random number from hardware
@ -14,7 +10,7 @@ Ant::Ant(PheromoneMap& pheromones, double x, double y)
direction = degree_distribution(gen); direction = degree_distribution(gen);
} }
Ant::Ant(PheromoneMap& pheromones, unsigned short direction) Ant::Ant(PheromoneMap& pheromones, unsigned int direction)
: WorldObject(0, 0, 3, sf::Color::Black), direction(direction), : WorldObject(0, 0, 3, sf::Color::Black), direction(direction),
pheromones(pheromones) { pheromones(pheromones) {
std::random_device device; // obtain a random number from hardware std::random_device device; // obtain a random number from hardware
@ -46,6 +42,7 @@ Ant::Ant(PheromoneMap& pheromones)
updateAppearance(); updateAppearance();
} }
// TODO: Unnecessary, only used for food/base
void Ant::addToUmwelt(const std::shared_ptr<WorldObject>& object) { void Ant::addToUmwelt(const std::shared_ptr<WorldObject>& object) {
umwelt.push_back(object); umwelt.push_back(object);
} }
@ -78,8 +75,10 @@ void Ant::move() {
attractor = NONE; attractor = NONE;
} }
for (const Pheromone& pheromone : pheromones.getInVision(*this, attractor, view_distance)) { for (const Pheromone& pheromone : pheromones.getInVision(*this, attractor, view_distance)) {
// TODO: What is this supposed to do?
} }
// TODO: Should this random generator be created on every move?
std::random_device device; // obtain a random number from hardware std::random_device device; // obtain a random number from hardware
std::mt19937 generator(device()); // seed the generator std::mt19937 generator(device()); // seed the generator
@ -87,7 +86,8 @@ void Ant::move() {
std::uniform_real_distribution<> degree_distribution(-std::numbers::pi, std::uniform_real_distribution<> degree_distribution(-std::numbers::pi,
std::numbers::pi); std::numbers::pi);
direction += degree_distribution(generator) * (1 / determination); direction += degree_distribution(generator) * (1 / determination); // Normalize with determination to smooth movement
// TODO: Use modulo
if (direction > 2 * std::numbers::pi) { if (direction > 2 * std::numbers::pi) {
direction -= 2 * std::numbers::pi; direction -= 2 * std::numbers::pi;
} }
@ -105,7 +105,7 @@ void Ant::updatePheromones() {
dropPheromone(); dropPheromone();
next_pheromone_drop = pheromone_interval + 1; next_pheromone_drop = pheromone_interval + 1;
} }
next_pheromone_drop = std::max(0, next_pheromone_drop - 1); next_pheromone_drop = std::max(0U, next_pheromone_drop - 1);
} }
PheroType Ant::getPheromoneType() const { PheroType Ant::getPheromoneType() const {
@ -121,6 +121,7 @@ void Ant::dropPheromone() {
pheromones.place(x, y, pheromone_type); pheromones.place(x, y, pheromone_type);
} }
// TODO: This is weird
void Ant::updateUmwelt() { void Ant::updateUmwelt() {
for (std::shared_ptr<WorldObject> const& obj : umwelt) { for (std::shared_ptr<WorldObject> const& obj : umwelt) {
if (obj->collides(*this)) { if (obj->collides(*this)) {

View File

@ -1,37 +1,43 @@
#ifndef H_ANT #ifndef H_ANT
#define H_ANT #define H_ANT
#include <memory>
#include <SFML/Graphics.hpp>
#include <string>
#include "colony.hpp" #include "colony.hpp"
#include "food.hpp" #include "food.hpp"
#include "pheromone_map.hpp" #include "pheromone_map.hpp"
#include "world_object.hpp" #include "world_object.hpp"
#include <cmath>
#include <iostream>
#include <memory>
#include <numbers>
#include <random>
#include <SFML/Graphics.hpp>
#include <string>
const double speed = 1; const double speed = 1;
const double determination = 25; // straightness of the path, (0, 1] const double determination = 25; // straightness of the path
const unsigned short pheromone_interval = 5; // updates between drops const unsigned int pheromone_interval = 5; // how many updates between drops
const unsigned short view_angle = 45; // angle degrees to each side const unsigned int view_angle = 45; // angle degrees to each side
const unsigned short view_distance = 25; const unsigned int view_distance = 25; // more like smell distance
class Ant : public WorldObject { class Ant : public WorldObject {
double direction; // in radians double direction; // in radians
// TODO: Should this be here or just global?
PheromoneMap& pheromones; PheromoneMap& pheromones;
unsigned short next_pheromone_drop = 0; unsigned int next_pheromone_drop = 0;
PheroType pheromone_type = NONE; // FOOD, HOME, NONE PheroType pheromone_type = NONE; // FOOD, HOME, NONE
public: public:
// TODO: Why is this stored here? I guess it can be removed
std::vector<std::shared_ptr<WorldObject>> umwelt; std::vector<std::shared_ptr<WorldObject>> umwelt;
public: public:
Ant(PheromoneMap& pheromones, double x, double y); Ant(PheromoneMap& pheromones, double x, double y);
Ant(PheromoneMap& pheromones, unsigned short direction); Ant(PheromoneMap& pheromones, unsigned int direction);
explicit Ant(PheromoneMap& pheromones); explicit Ant(PheromoneMap& pheromones);
// TODO: Regarding umwelt
void addToUmwelt(const std::shared_ptr<WorldObject>& object); void addToUmwelt(const std::shared_ptr<WorldObject>& object);
void update() override; void update() override;
@ -41,6 +47,8 @@ public:
void updateAppearance(); void updateAppearance();
void updatePheromones(); void updatePheromones();
void dropPheromone(); // red void dropPheromone(); // red
// TODO: Regarding umwelt
void updateUmwelt(); void updateUmwelt();
}; };

View File

@ -10,7 +10,6 @@ public:
Colony(double x, double y); Colony(double x, double y);
void update() override; void update() override;
PheroType getPheromoneType() const override; PheroType getPheromoneType() const override;
}; };

View File

@ -10,7 +10,6 @@ public:
Food(double x, double y); Food(double x, double y);
void update() override; void update() override;
PheroType getPheromoneType() const override; PheroType getPheromoneType() const override;
}; };

View File

@ -11,11 +11,11 @@
#include "pheromone.hpp" #include "pheromone.hpp"
#include "pheromone_map.hpp" #include "pheromone_map.hpp"
const unsigned short HEIGHT = 500; const unsigned int HEIGHT = 500;
const unsigned short WIDTH = 500; const unsigned int WIDTH = 500;
const unsigned short FPS = 60; const unsigned int FPS = 60;
const unsigned short ANTCOUNT = 100; const unsigned int ANTCOUNT = 100;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
sf::ContextSettings settings; sf::ContextSettings settings;
@ -24,8 +24,8 @@ int main(int argc, char* argv[]) {
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Ants", sf::Style::Close, settings); sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Ants", sf::Style::Close, settings);
window.setFramerateLimit(FPS); // Limit FPS window.setFramerateLimit(FPS); // Limit FPS
float t = 0.0; // Verstrichene Zeit in ms double t = 0.0; // Verstrichene Zeit in ms
float dt = 1.0 / FPS; // Schrittweite in ms double dt = 1.0 / FPS; // Schrittweite in ms
PheromoneMap pheromones; PheromoneMap pheromones;
std::vector<std::unique_ptr<Ant>> ants; // Use pointer bc we can't instatiate abstract classes std::vector<std::unique_ptr<Ant>> ants; // Use pointer bc we can't instatiate abstract classes
@ -42,8 +42,9 @@ int main(int argc, char* argv[]) {
ant->addToUmwelt(foodA); ant->addToUmwelt(foodA);
} }
// Main event loop
while (window.isOpen()) { while (window.isOpen()) {
// Main event loop
sf::Event event {}; sf::Event event {};
while (window.pollEvent(event)) { while (window.pollEvent(event)) {

View File

@ -3,8 +3,6 @@
// //
#include "pheromone.hpp" #include "pheromone.hpp"
#include "world_object.hpp"
#include <SFML/Graphics.hpp>
Pheromone::Pheromone(double x, double y, PheroType type) Pheromone::Pheromone(double x, double y, PheroType type)
: WorldObject(x, y, 2, sf::Color::Transparent) { : WorldObject(x, y, 2, sf::Color::Transparent) {
@ -28,7 +26,7 @@ PheroType Pheromone::getPheromoneType() const {
} }
void Pheromone::update() { void Pheromone::update() {
intensity = std::max(0, intensity - decay); intensity = std::max(0U, intensity - decay);
appearance.setFillColor(sf::Color( appearance.setFillColor(sf::Color(
appearance.getFillColor().r, appearance.getFillColor().r,
appearance.getFillColor().g, appearance.getFillColor().g,

View File

@ -8,13 +8,14 @@
#include "world_object.hpp" #include "world_object.hpp"
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
const unsigned short decay = 1; // TODO: Use percentage
const unsigned int decay = 1;
class Pheromone : public WorldObject { class Pheromone : public WorldObject {
public: public:
unsigned short intensity = 255; // TODO: Use 1.0 to 0.0 double
unsigned int intensity = 255;
public:
Pheromone(double x, double y, PheroType type); Pheromone(double x, double y, PheroType type);
PheroType getPheromoneType() const override; PheroType getPheromoneType() const override;

View File

@ -1,6 +1,4 @@
#include "pheromone_map.hpp" #include "pheromone_map.hpp"
#include "ant.hpp"
#include <iostream>
void PheromoneMap::place(double x, double y, PheroType type) { void PheromoneMap::place(double x, double y, PheroType type) {
pheromones.emplace_back(x, y, type); pheromones.emplace_back(x, y, type);

View File

@ -1,7 +1,9 @@
#ifndef __PHEROMONES_H_ #ifndef __PHEROMONES_H_
#define __PHEROMONES_H_ #define __PHEROMONES_H_
#include "ant.hpp"
#include "pheromone.hpp" #include "pheromone.hpp"
#include <iostream>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <vector> #include <vector>
@ -9,12 +11,12 @@ class Ant;
class PheromoneMap { class PheromoneMap {
public: public:
// TODO: Use fixed size matrix (and only int locations) for this, currently it's just slow
std::vector<Pheromone> pheromones; std::vector<Pheromone> pheromones;
public: // TODO: Move this to ant
void place(double x, double y, PheroType type);
std::vector<Pheromone> getInVision(const Ant& ant, PheroType type, unsigned short radius); std::vector<Pheromone> getInVision(const Ant& ant, PheroType type, unsigned short radius);
void place(double x, double y, PheroType type);
void update(); void update();
}; };

View File

@ -1,6 +1,6 @@
#include "world_object.hpp" #include "world_object.hpp"
WorldObject::WorldObject(double x, double y, unsigned short radius, sf::Color color) WorldObject::WorldObject(double x, double y, unsigned int radius, sf::Color color)
: x(x), y(y), radius(radius) { : x(x), y(y), radius(radius) {
appearance = sf::CircleShape(radius); appearance = sf::CircleShape(radius);
appearance.setFillColor(color); appearance.setFillColor(color);

View File

@ -4,9 +4,11 @@
#include <cmath> #include <cmath>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
extern const unsigned short WIDTH; // TODO: Move definitions to header and use constexpr/macro
extern const unsigned short HEIGHT; extern const unsigned int WIDTH;
extern const unsigned int HEIGHT;
// TODO: Just use FOOD
enum PheroType { enum PheroType {
FOOD, FOOD,
HOME, HOME,
@ -16,24 +18,21 @@ enum PheroType {
class WorldObject { class WorldObject {
protected: protected:
double x, y; double x, y;
const unsigned short radius; const unsigned int radius;
WorldObject(double x, double y, unsigned int radius, sf::Color color);
public: public:
sf::CircleShape appearance; sf::CircleShape appearance;
protected: bool isOffScreen() const;
WorldObject(double x, double y, unsigned short radius, sf::Color color);
public:
bool isOffScreen() const; // virtual: late-binding, no static linkage
bool collides(const WorldObject& other) const; bool collides(const WorldObject& other) const;
double distance(const WorldObject& other) const; double distance(const WorldObject& other) const;
double angle(const WorldObject& other) const; double angle(const WorldObject& other) const;
virtual void update() = 0; // pure virtual: has to be overridden // TODO: Switch to only food pheromones
virtual PheroType getPheromoneType() const = 0; virtual PheroType getPheromoneType() const = 0;
virtual void update() = 0; // pure virtual: has to be overridden
}; };
#endif // __OBJECT_H_ #endif // __OBJECT_H_