#include <iostream>
using namespace std;
enum Direction {
    North,
    East,
    South,
    West,
};
class MapSite {
public:
    virtual void Enter() = 0;
};
class Room : public MapSite {
public:
    Room(int roomNo):_roomNumber(roomNo) {};
    MapSite *GetSide(Direction) const;
    virtual void SetSide(Direction direction, MapSite *) {
        cout << "Set the "
            << _roomNumber
            << " room "
            << direction
            << " side."
            << endl;
    };
    int GetRoomNo() {
        return _roomNumber;
    };
    virtual void Enter() {
        cout << "Enter the Room." << endl;
    };
private:
    MapSite *_sides[4];
    int _roomNumber;
};
class BombRoom : public Room {
public:
    BombRoom(int num):Room(num) 
    {
        _roomNum = num;
    };
    virtual void SetSide(Direction direction, MapSite *) {
        cout << "Set the "
            << _roomNum
            << " bomb room "
            << direction
            << " side."
            << endl;
    };
private:
    int _roomNum;
};
class Wall : public MapSite {
public:
    Wall() {};
    virtual void Enter() {
        cout << "Enter the wall." << endl;
    };
};
class Door : public MapSite {
public:
    Door(Room* = 0, Room* = 0) {};
    virtual void Enter() 
    {
        cout << "Enter the door." << endl;
    };
    Room *OtherSideFrom(Room*) {};
private:
    Room *_room1;
    Room *_room2;
    bool _isOpen;
};
class Maze {
public:
    Maze() {};
    void AddRoom(Room* room) {
        cout << "Add the room" << room->GetRoomNo() << "." << endl;
    };
    Room* RoomNo(int) const{};
};
class MazeFactory {
public:
    MazeFactory() {};
    virtual Maze* MakeMaze() const {
        return new Maze;
    };
    virtual Wall* MakeWall() const {
        return new Wall;
    };
    virtual Room* MakeRoom(int n) const {
        return new Room(n);
    };
    virtual Door* MakeDoor(Room* r1, Room* r2) const {
        return new Door(r1, r2);
    };
};
class BombMazeFactory : public MazeFactory {
public:
    virtual Room* MakeRoom(int n) const {
        return new BombRoom(n);
    };
};
class MazeGame {
public:
    Maze* CreateMaze(MazeFactory &factory) {
        Maze* aMaze = factory.MakeMaze();
        Room* r1 = factory.MakeRoom(1);
        Room* r2 = factory.MakeRoom(2);
        Door* theDoor = factory.MakeDoor(r1, r2);
        aMaze->AddRoom(r1);
        aMaze->AddRoom(r2);
        r1->SetSide(North, factory.MakeWall());
        r1->SetSide(East, theDoor);
        r1->SetSide(South, factory.MakeWall());
        r1->SetSide(West, factory.MakeWall());
        r2->SetSide(North, factory.MakeWall());
        r2->SetSide(East, factory.MakeWall());
        r2->SetSide(South, factory.MakeWall());
        r2->SetSide(West, theDoor);
        return aMaze;
    };
};
int main() {
    MazeGame mygame;
    //  MazeFactory factory;
    BombMazeFactory factory;
    mygame.CreateMaze(factory);
    system("pause");
    return 0;
}