Files
GameOfLifeEditor/src/world.cpp
2026-01-10 22:01:15 +01:00

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;
}