/* * File name: world.cpp * Author: lejulien * Date created: 09-01-2026 23:59:55 // Date modified: 10-01-2026 22:00:23 * ------ */ #include "../includes/world.hpp" #include // Constructor and destructor World::World(int width, int height) : _width(width), _height(height) { // create world data this->_data = new std::vector(width * height, false); } World::~World() { delete this->_data; } // Getters std::vector *World::getWorldData() { return this->_data; } int World::getWidth() { return this->_width; } int World::getHeight() { return this->_height; } // Member function void World::randomize() { // setup randomization _history.clear(); _cycle_index = 0; auto now = std::chrono::high_resolution_clock::now(); auto ms = std::chrono::duration_cast( now.time_since_epoch()) .count(); std::srand(ms); // filling data with random states for (auto cell : *this->_data) { if (std::rand() % 2) cell = true; else cell = false; } } std::vector World::getCompressed() { if (!_data || _data->empty()) { return {}; } bool previous_state = (*_data)[0]; std::vector compressed_out; compressed_out.push_back(_width); compressed_out.push_back(_height); compressed_out.push_back((previous_state) ? 1 : 0); unsigned int count = 0; for (auto state : *_data) { if (state != previous_state) { compressed_out.push_back(count); previous_state = state; count = 1; continue; } count++; } compressed_out.push_back(count); return compressed_out; } void World::loadCompressed(const std::vector &compressed) { if (compressed.empty()) { std::cerr << "Error: Compressed data is empty." << std::endl; return; } auto it = compressed.begin(); int width = *it++; int height = *it++; bool actual_state = (*it++ == 1); auto new_data = new std::vector(); while (it != compressed.end()) { unsigned int count = *it++; for (unsigned int i = 0; i < count; ++i) { new_data->push_back(actual_state); } actual_state = !actual_state; } delete this->_data; this->_data = new_data; this->_width = width; this->_height = height; } void World::saveCompressed() { _cycle_index++; if (_history.size() >= MAX_HISTORY_SIZE) { _history.erase(_history.begin()); } _history.push_back(getCompressed()); } void World::clear() { _history.clear(); _cycle_index = 0; for (auto cell : *this->_data) { cell = false; } } void World::stepBack() { if (_history.empty()) { std::cerr << "Error: Invalid history index." << std::endl; // [TODO] Generate new history from initial state to _history_index; return; } _cycle_index--; loadCompressed(_history[_history.size() - 1]); _history.resize(_history.size() - 1); } void World::setCell(int x, int y) { _history.clear(); _cycle_index = 0; if (!_data) { return; } (*_data)[x + y * _width] = !(*_data)[x + y * _width]; } void World::resize(int width, int height) { _width = width; _height = height; _data->resize(width * height, false); clear(); } std::vector World::getSelection(Vector2i &origin, Vector2i &size) { // We assume the selection is in the grid for now std::vector data = {static_cast(size.x), static_cast(size.y)}; for (int y = origin.y; y < origin.y + size.y; y++) { for (int x = origin.x; x < origin.x + size.x; x++) { data.push_back((*_data)[x + y * _width]); } } return data; }