#include <memory>
#include <iostream>

using namespace std;

class Vehicle {
public:
    virtual void move()  = 0;
};

class NormalVehicle : public Vehicle {
    virtual void move() { cout << "move" << endl; }
};

//tutaj dla wygody używam sprytnych wskaźników (shared_ptr), ale nie jest to częścią zadania
using PVehicle = shared_ptr<Vehicle>;

class Decorator : public Vehicle {
public:
    Decorator(PVehicle obj) : obj_(obj) {}
    virtual void move() { obj_->move(); }
private:
    PVehicle obj_;
};

class Lidar : public Decorator {
public:
    Lidar(PVehicle obj) : Decorator(obj) {}
    virtual void move() {
        cout << "lidar " << flush;
        bool lidar_alarm = false; //symuluje sensor
        if(!lidar_alarm)
          Decorator::move();
    }
};

class Radar : public Decorator {
public:
    Radar(PVehicle obj) : Decorator(obj) {}
    virtual void move() {
        cout << "radar " << flush;
        bool radar_alarm = false; //symuluje sensor
        if(!radar_alarm)
          Decorator::move();
    }
};

class Camera : public Decorator {
public:
    Camera(PVehicle obj) : Decorator(obj) {}
    virtual void move() {
        cout << "camera " << flush;
        bool camera_alarm = false; //symuluje sensor
        if(!camera_alarm)
          Decorator::move();
    }
};

int main() {
    PVehicle normal = PVehicle(new NormalVehicle);
    normal->move();
    PVehicle lidar = PVehicle(new Lidar( PVehicle(new NormalVehicle) ) );
    lidar->move();
    PVehicle radar = PVehicle(new Radar( PVehicle(new NormalVehicle) ) );
    radar->move();
    PVehicle camera = PVehicle(new Camera( PVehicle(new NormalVehicle) ) );
    camera->move();
    PVehicle all = PVehicle(new Lidar( PVehicle(new Radar( PVehicle(new Camera( PVehicle(new NormalVehicle)))))));
    all->move();
    return 0;
}

class Vehicle2 {
    virtual void move() { cout << "move" << endl; }
};

class Vehicle2Lidar : public Vehicle2 {
    void move() override {
        bool lidar_alarm = false; //symuluje sensor
        if(! lidar_alarm) Vehicle2::move();
    }
};

class Vehicle2Radar : public Vehicle2 {
    void move() override {
        bool radar_alarm = false; //symuluje sensor
        if(! radar_alarm) Vehicle2::move();
    }

};

class Vehicle2Camera : public Vehicle2 {
    void move() override {
        bool camera_alarm = false; //symuluje sensor
        if(! camera_alarm) Vehicle2::move();
    }

};

class Vehicle2LidarRadar : public Vehicle2 {
    void move() override {
        bool lidar_alarm = false; //symuluje sensor
        bool radar_alarm = false; //symuluje sensor
        if(! lidar_alarm && ! radar_alarm ) Vehicle2::move();
    }

};

class Vehicle2RadarCamera : public Vehicle2 {
    void move() override {
        bool radar_alarm = false; //symuluje sensor
        bool camera_alarm = false; //symuluje sensor
        if(! radar_alarm && ! camera_alarm) Vehicle2::move();
    }

};

class Vehicle2CameraLidar : public Vehicle2 {
    void move() override {
        bool camera_alarm = false; //symuluje sensor
        bool lidar_alarm = false; //symuluje sensor
        if(!camera_alarm && ! lidar_alarm) Vehicle2::move();
    }

};

class Vehicle2RadarLidarCamera : public Vehicle2 {
    void move() override {
        bool radar_alarm = false; //symuluje sensor
        bool lidar_alarm = false; //symuluje sensor
        bool camera_alarm = false; //symuluje sensor
        if(!radar_alarm && ! lidar_alarm && !camera_alarm) Vehicle2::move();
    }

};

