#include "level.h" #include #include #include template // [D]erived - [B]ase std::unique_ptr static_unique_pointer_cast(std::unique_ptr&& old) { return std::unique_ptr{static_cast(old.release())}; } void Level::Map::init(const std::string &path) { prepareDefaultCells(); std::ifstream file; file.open(path); std::string cur_line; std::istringstream sstr; SECTION cur_section = SECTION::NONE; while (getline(file, cur_line)) { if (map_section.find(cur_line) != map_section.end()) { cur_section = map_section[cur_line]; continue; } sstr.clear(); sstr.str(cur_line); switch (cur_section) { case SECTION::SIZE: readMapSize(sstr); break; case SECTION::MAP: readMapRow(sstr); break; case SECTION::TELEPORT: case SECTION::CHARGE: case SECTION::TRIGGER: readCellSection(sstr, cur_section); break; default: break; } } file.close(); } void Level::Map::prepareDefaultCells() { default_cells[PASSABLE_CELL] = std::make_unique(); default_cells[WATER_CELL] = std::make_unique(); default_cells[WALL_CELL] = std::make_unique(); default_cells[CHARGE_CELL] = std::make_unique(); default_cells[EXIT_CELL] = std::make_unique(); default_cells[TELEPORT_CELL] = std::make_unique(); default_cells[TRIGGER_CELL] = std::make_unique(); } void Level::Map::readMapSize(std::istringstream &sstr) { sstr >> rows >> cols; data.reserve(rows * cols); } void Level::Map::readMapRow(std::istringstream &sstr) { data.emplace_back(Row()); int cell_type; while (sstr >> cell_type) { data.back().emplace_back(default_cells[cell_type]->clone()); data.back().back()->setPosition(data.size()-1, data.back().size()-1); } } void Level::Map::readCellSection(std::istringstream &sstr, const SECTION §ion) { coordinate src_row, src_col; sstr >> src_row >> src_col; switch (section) { case SECTION::TELEPORT: data[src_row][src_col] = readTeleport(sstr, static_unique_pointer_cast(std::move(data[src_row][src_col]))); break; case SECTION::CHARGE: data[src_row][src_col] = readCharge(sstr, static_unique_pointer_cast(std::move(data[src_row][src_col]))); break; case SECTION::TRIGGER: data[src_row][src_col] = readTrigger(sstr, static_unique_pointer_cast(std::move(data[src_row][src_col]))); break; default: break; } } std::unique_ptr &&Level::Map::readTeleport(std::istringstream &sstr, std::unique_ptr &&cell) { coordinate dest_row, dest_col; sstr >> dest_row >> dest_col; cell->setDestination(dest_row, dest_col); return std::move(cell); } std::unique_ptr &&Level::Map::readCharge(std::istringstream &sstr, std::unique_ptr &&cell) { int num_charges; sstr >> num_charges; cell->setCharges(num_charges); return std::move(cell); } std::unique_ptr &&Level::Map::readTrigger(std::istringstream &sstr, std::unique_ptr &&cell) { coordinate dest_row, dest_col; int cell_type; sstr >> dest_row >> dest_col >> cell_type; auto dest_cell = default_cells[cell_type]->clone(); dest_cell->setPosition(dest_row, dest_col); switch (cell_type) { case TELEPORT_CELL: dest_cell = readTeleport(sstr, static_unique_pointer_cast(std::move(dest_cell))); break; case CHARGE_CELL: dest_cell = readCharge(sstr, static_unique_pointer_cast(std::move(dest_cell))); break; case TRIGGER_CELL: dest_cell = readTrigger(sstr, static_unique_pointer_cast(std::move(dest_cell))); break; default: break; } cell->addTarget(std::move(dest_cell)); return std::move(cell); } Level::Level(const std::string &path) { map.init(path); } size_t Level::rows() const { return map.rows; } size_t Level::cols() const { return map.cols; } std::unique_ptr &Level::getCellAt(coordinate row, coordinate col) { return map.data[row][col]; } void Level::placeBridge(coordinate row, coordinate col) { map.data[row][col] = std::make_unique(row, col, palette::Black); } void Level::removeCharge(coordinate row, coordinate col) { map.data[row][col] = std::make_unique(row, col, color_ground); } sf::Color Level::defaultGroundColor() { return color_ground; } void Level::setDefaultGroundColor(const sf::Color &color) { color_ground = color; }