ICT290 / src / scene / AIController / ArcanistLevel.cpp
ArcanistLevel.cpp
Raw
#include "ArcanistLevel.h"
#include <algorithm>
#include <random>

ArcanistLevel::~ArcanistLevel() {
    for (auto& m_allObstacle : m_allObstacles) {
        delete m_allObstacle;
    }
}

const Room& ArcanistLevel::getRoom(std::size_t i) const {
    if (i < m_rooms.size() && i > 0) {
        return m_rooms[i];
    }
    throw std::invalid_argument(
        "ArchanistLevel::getRoom, Index out of bounds.\n");
}

const std::vector<Room>& ArcanistLevel::getRooms() const {
    return m_rooms;
}

const Room& ArcanistLevel::getNearestRoom(const glm::vec2& position) const {
    auto room = std::find_if(m_rooms.begin(),
                             m_rooms.end(),
                             [position](const Room& room) {
                                 if (position.x >= room.min.x
                                     && position.y >= room.min.y
                                     && position.x <= room.max.x
                                     && position.y <= room.max.y) {
                                     return true;
                                 }
                                 return false;
                             });
    if (room != m_rooms.end()) {
        return *room;
    } else {
        throw std::runtime_error("getNearestRoom out of bound position\n");
    }
}

bool ArcanistLevel::isInBounds(const glm::vec2& position) const {
    auto room = std::find_if(m_rooms.begin(),
                             m_rooms.end(),
                             [position](const Room& room) {
                                 if (position.x >= room.min.x + 0.25f
                                     && position.y >= room.min.y + 0.25f
                                     && position.x <= room.max.x - 1.25f
                                     && position.y <= room.max.y - 1.25f) {
                                     return true;
                                 }
                                 return false;
                             });
    if (room != m_rooms.end()) {
        return true;
    }
    return false;
}

bool ArcanistLevel::isInBoundsTight(const glm::vec2& position) const {
    auto room = std::find_if(m_rooms.begin(),
                             m_rooms.end(),
                             [position](const Room& room) {
                                 if (position.x >= room.min.x + 0.5f
                                     && position.y >= room.min.y + 0.5f
                                     && position.x <= room.max.x - 1.5f
                                     && position.y <= room.max.y - 1.5f) {
                                     return true;
                                 }
                                 return false;
                             });
    if (room != m_rooms.end()) {
        return true;
    }
    return false;
}

void ArcanistLevel::updateAllWalls() {
    m_allWalls.clear();
    std::for_each(m_rooms.begin(), m_rooms.end(), [this](const Room& room) {
        std::copy(room.walls.begin(),
                  room.walls.end(),
                  std::back_inserter(m_allWalls));
    });
}

void ArcanistLevel::updateAllEntities() {
    m_allObstacles.clear();
    std::for_each(m_rooms.begin(), m_rooms.end(), [this](const Room& room) {
        std::copy(room.obstacles.begin(),
                  room.obstacles.end(),
                  std::back_inserter(m_allObstacles));
    });
}

const std::vector<WallType>& ArcanistLevel::getAllWalls() const {
    return m_allWalls;
}

const std::vector<BasicEntity*>& ArcanistLevel::getAllObstacles() const {
    return m_allObstacles;
}

glm::vec2 ArcanistLevel::getRandomSpawn() {
    // Pick random room that isn't spawn or a corridor
    std::random_device rd{};  /// obtain a random number from hardware
    std::mt19937 gen{rd()};   /// seed the generator
    std::uniform_int_distribution<> distribution{1,
                                                 (int)m_numOfRooms
                                                     - 1};  /// define the range

    auto& room = m_rooms[distribution(gen)];

    return getRandomSpawn(room);
}

glm::vec2 ArcanistLevel::getRandomSpawn(int seed) {
    // Pick random room that isn't spawn or a corridor
    std::mt19937 gen{static_cast<std::random_device::result_type>(
        seed)};  /// seed the generator
    std::uniform_int_distribution<> distribution{1,
                                                 (int)m_numOfRooms
                                                     - 1};  /// define the range

    const auto& room = m_rooms[distribution(gen)];

    return getRandomSpawn(room, seed);
}

glm::vec2 ArcanistLevel::getRandomSpawn(const Room& room) {
    std::random_device rd{};  /// obtain a random number from hardware
    std::mt19937 gen{rd()};   /// seed the generator
    std::uniform_int_distribution<> xDist{(int)room.min.x + 1,
                                          (int)room.max.x
                                              - 2};  /// define the range

    std::uniform_int_distribution<> yDist{(int)room.min.y + 1,
                                          (int)room.max.y - 2};

    return glm::vec2{(float)xDist(gen), (float)yDist(gen)};
}

glm::vec2 ArcanistLevel::getRandomSpawn(const Room& room, int seed) {
    std::mt19937 gen{static_cast<std::random_device::result_type>(seed)};
    std::uniform_int_distribution<> xDist{(int)room.min.x + 1,
                                          (int)room.max.x
                                              - 2};  /// define the range

    std::uniform_int_distribution<> yDist{(int)room.min.y + 1,
                                          (int)room.max.y - 2};

    return glm::vec2{(float)xDist(gen), (float)yDist(gen)};
}