#include #include #include #include #include #include using namespace std; using Point = std::pair; class Object { public: Object(int x, int y, string name) : position{x, y}, name{name} {} virtual ~Object() = default; Object(Object const &) = delete; virtual bool collide(Object const &other) const { return position == other.position; } Point get_position() const { return position; } string get_name() const { return name; } protected: Point position; string const name; }; class Wall : public Object { public: using Object::Object; }; class Door : public Wall { public: using Wall::Wall; }; class Movable : public Object { public: using Object::Object; void move_to(Point new_position) { position = new_position; } virtual void move() = 0; }; class Human : public Movable { public: using Movable::Movable; // using typeid to check against one specific type. Only doing dynamic_cast here // will not work sice Door will also be a valid cast. bool collide(Object const &other) const override { return Object::collide(other) && typeid(other) == typeid(Wall); } void move() override { ++position.second; } }; class Cat : public Movable { public: using Movable::Movable; bool collide(Object const &other) const override { if (Object::collide(other)) { return dynamic_cast(&other) != nullptr; } return false; } void move() override { ++position.first; } }; bool have_collisions(Movable &obj, std::vector> const &objects) { return any_of(begin(objects), end(objects), [&obj](auto const & optr){ return obj.collide(*optr); }); } void update(std::vector> &objects) { for (auto & obj : objects) { if (auto mov = dynamic_cast(obj.get())) { auto old_position{mov->get_position()}; mov->move(); if (have_collisions(*mov, objects)) { mov->move_to(old_position); } else { cout << mov->get_name() << " moved!" << endl; } } } } int main() { std::vector> objects; objects.push_back(make_unique(-2, 2, "the cat")); objects.push_back(make_unique(4, 2, "east wall")); objects.push_back(make_unique(2, 0, "the human")); objects.push_back(make_unique(2, 2, "the front door")); objects.push_back(make_unique(2, 5, "outer wall")); for (int i{0}; i < 10; ++i) update(objects); }