#include #include #include #include #include #include #include #include namespace ecs { namespace entity { using id = size_t; using entities = std::vector; } namespace component { using name = std::string; using is_male = bool; using detail = std::pair; using detail_component = std::pair; enum class type { algue, Mérou, Thon, PoissonClown, Sole, Bar, Carpe }; using type_component = std::pair; } namespace system { using details = std::vector; using types = std::vector; } namespace internal { entity::entities _entities; system::details _details; system::types _types; std::random_device _random_device; std::default_random_engine _random_engine { _random_device() }; } bool is_algue(component::type t) { return (t == component::type::algue); } bool is_poisson(component::type t) { return !is_algue(t); } bool is_carnivore(component::type t) { return (t == component::type::Mérou || t == component::type::Thon || t == component::type::PoissonClown); } bool is_herbivore(component::type t) { return (t == component::type::Sole || t == component::type::Bar || t == component::type::Carpe); } std::string to_string(component::type t) { static const std::string types[] = { "Algue", "Mérou", "Thon", "Poisson-clown", "Sole", "Bar", "Carpe" }; const auto i = static_cast(t); return types[i]; } template std::vector get_entities(Predicat&& predicat) { std::vector algues; std::for_each(begin(internal::_types), end(internal::_types), [&algues, predicat](auto p){ if (predicat(p.second)) { algues.push_back(p.first); } } ); return algues; } template typename Collection::value_type const& get_component(Collection const& components, entity::id id) { const auto it = find_if(begin(components), end(components), [id](auto p){ return (p.first == id); }); assert(it != end(components)); return (*it); } entity::id create_entity() { const auto id = internal::_entities.empty() ? 0 : internal::_entities.back() + 1; internal::_entities.push_back(id); return id; } entity::id add_algue() { const auto id = create_entity(); internal::_types.push_back(std::make_pair(id, component::type::algue)); return id; } entity::id add_poisson(component::type t, component::name n, component::is_male m) { assert(is_poisson(t)); const auto id = create_entity(); internal::_types.push_back(std::make_pair(id, t)); internal::_details.push_back(std::make_pair(id, make_pair(n, m))); return id; } void remove_entity(entity::id id) { const auto entities_it = std::remove(internal::_entities.begin(), internal::_entities.end(), id); internal::_entities.erase(entities_it, internal::_entities.end()); const auto details_it = std::remove_if(internal::_details.begin(), internal::_details.end(), [id](auto p){ return (p.first == id); }); internal::_details.erase(details_it, internal::_details.end()); const auto types_it = std::remove_if(internal::_types.begin(), internal::_types.end(), [id](auto p){ return (p.first == id); }); internal::_types.erase(types_it, internal::_types.end()); } void remove_entities(std::vector const& ids) { for (auto id: ids) remove_entity(id); } void print_algues() { const auto count = std::count_if(begin(internal::_types), end(internal::_types), [](auto p){ return (p.second == component::type::algue); }); std::cout << "algues: " << count; } void print_poissons() { if (internal::_details.empty()) { std::cout << "No poissons"; return; } std::cout << internal::_details.size() << " poissons: "; auto print = [](auto p){ return (p.second.first + " [" + (p.second.second ? 'M' : 'F') + ']'); }; std::transform(begin(internal::_details), end(internal::_details) - 1, std::ostream_iterator(std::cout, ", "), print); std::cout << print(internal::_details.back()); } void print() { print_algues(); std::cout << ". "; print_poissons(); std::cout << '.' << std::endl; } } int main() { for (size_t i {}; i < 50; ++i) ecs::add_algue(); for (size_t i {}; i < 10; ++i) ecs::add_poisson(ecs::component::type::Sole, "toto", false); for (size_t i {}; i < 5; ++i) ecs::add_poisson(ecs::component::type::Mérou, "titi", false); ecs::print(); for (size_t tour {}; tour < 10; ++tour) { std::cout << "===== Tour " << tour << " ======" << std::endl; std::vector entities_to_remove; const auto poissons { ecs::get_entities(ecs::is_poisson) }; const auto algues { ecs::get_entities(ecs::is_algue) }; std::uniform_int_distribution entities_distribution(0, ecs::internal::_entities.size() - 1); std::uniform_int_distribution algue_distribution(0, algues.size() - 1); for (auto poisson: poissons) { auto const& poisson_type = ecs::get_component(ecs::internal::_types, poisson); if (ecs::is_herbivore(poisson_type.second) && !algues.empty()) { const auto index { algue_distribution(ecs::internal::_random_engine) }; const auto target = algues[index]; entities_to_remove.push_back(target); } else if (ecs::is_carnivore(poisson_type.second) && !ecs::internal::_entities.empty()) { const auto index { entities_distribution(ecs::internal::_random_engine) }; const auto target = ecs::internal::_entities[index]; entities_to_remove.push_back(target); } } ecs::remove_entities(entities_to_remove); ecs::print(); } return 0; }