152 lines
3.6 KiB
C++
152 lines
3.6 KiB
C++
/*
|
|
* 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 <chrono>
|
|
|
|
// Constructor and destructor
|
|
|
|
World::World(int width, int height) : _width(width), _height(height) {
|
|
// create world data
|
|
this->_data = new std::vector<bool>(width * height, false);
|
|
}
|
|
|
|
World::~World() { delete this->_data; }
|
|
|
|
// Getters
|
|
|
|
std::vector<bool> *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<std::chrono::milliseconds>(
|
|
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<uint32_t> World::getCompressed() {
|
|
if (!_data || _data->empty()) {
|
|
return {};
|
|
}
|
|
bool previous_state = (*_data)[0];
|
|
std::vector<uint32_t> 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<uint32_t> &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<bool>();
|
|
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<uint32_t> World::getSelection(Vector2i &origin, Vector2i &size) {
|
|
// We assume the selection is in the grid for now
|
|
std::vector<uint32_t> data = {static_cast<uint32_t>(size.x),
|
|
static_cast<uint32_t>(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;
|
|
}
|