Files
jminos/src/Pieces/PiecesFiles.cpp
Persson-dev 46b9b8dd65
Some checks failed
Linux arm64 / Build (push) Failing after 2m4s
begin optimize Generator
2025-07-19 23:39:22 +02:00

156 lines
4.4 KiB
C++

#include "PiecesFiles.h"
#include "Generator.h"
#include "Piece.h"
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <algorithm>
#include "../Common/Compression.h"
PiecesFiles::PiecesFiles() {
}
bool PiecesFiles::savePieces(int polyominoSize) const {
std::string filePath;
if (!this->getFilePath(polyominoSize, filePath)) {
return false;
}
Generator generator;
std::vector<Polyomino> polyominoes = generator.generatePolyominoes(polyominoSize);
return this->savePieces(polyominoSize, polyominoes);
}
bool PiecesFiles::savePieces(int polyominoSize, std::vector<Polyomino>& polyominoes) const {
std::string filePath;
if (!this->getFilePath(polyominoSize, filePath)) {
return false;
}
constexpr std::size_t INITIAL_CAPACITY = 2048;
DataBuffer buffer(INITIAL_CAPACITY);
// sorting the polyominoes is done after setting spawn position to ensure the order is always the same
for (Polyomino& nMino : polyominoes) {
nMino.goToSpawnPosition();
}
std::sort(polyominoes.begin(), polyominoes.end());
for (const Polyomino& polyomino : polyominoes) {
// write the characteristics of the piece
bool isConvex = polyomino.isConvex();
bool hasHole = (isConvex) ? false : polyomino.hasHole();
std::uint8_t infoByte = (isConvex << 7) + (hasHole << 6) + polyomino.getLength();
buffer << infoByte;
// write the positions of the piece
std::uint8_t positionByte;
for (const Position position : polyomino.getPositions()) {
positionByte = (position.x << 4) + position.y;
buffer << positionByte;
}
}
DataBuffer compressed = Compress(buffer);
return compressed.WriteFile(filePath);
}
bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std::vector<int>& convexPieces, std::vector<int>& holelessPieces, std::vector<int>& otherPieces) const {
std::string filePath;
if (!this->getFilePath(polyominoSize, filePath)) {
return false;
}
DataBuffer compressed;
if(!compressed.ReadFile(filePath))
return false;
DataBuffer buffer = Decompress(compressed, compressed.GetSize());
std::ifstream piecesFile(filePath, std::ios::binary);
if (!piecesFile.good()) {
return false;
}
pieces.clear();
convexPieces.clear();
holelessPieces.clear();
otherPieces.clear();
// we shift the first color of each size so that the small polyominoes (size 1-2-3) don't all have the same color
Block pieceBlock = firstPieceBlockType();
for (int i = 0; i < polyominoSize; i++) {
nextPieceBlockType(pieceBlock);
}
char convexMask = 0b1000'0000;
char holeMask = 0b0100'0000;
char lengthMask = 0b0011'1111;
char xMask = 0b1111'0000;
char yMask = 0b0000'1111;
std::uint8_t infoByte;
int i = 0;
while (!buffer.IsFinished()) {
// if (piecesFile.eof()) break;
buffer >> infoByte;
// read piece infos
bool isConvex = (infoByte & convexMask) >> 7;
bool hasHole = (infoByte & holeMask) >> 6;
int length = (infoByte & lengthMask);
// read positions
std::set<Position> piecePositions;
std::uint8_t positionByte;
for (int i = 0; i < polyominoSize; i++) {
buffer >> positionByte;
int x = ((unsigned char) positionByte & xMask) >> 4;
int y = positionByte & yMask;
piecePositions.insert(Position(x, y));
}
// create piece
Piece readPiece(Polyomino(std::move(piecePositions), length), pieceBlock);
nextPieceBlockType(pieceBlock);
pieces.push_back(readPiece);
if (isConvex) {
convexPieces.push_back(i);
}
else if (hasHole) {
otherPieces.push_back(i);
}
else {
holelessPieces.push_back(i);
}
i++;
}
return true;
}
bool PiecesFiles::getFilePath(int polyominoSize, std::string& filePath) const {
std::string dataFolderPath = "data/pieces/";
if (!std::filesystem::exists(dataFolderPath)) {
std::filesystem::create_directories(dataFolderPath);
}
if (!std::filesystem::is_directory(dataFolderPath)) {
return false;
}
filePath = dataFolderPath + std::to_string(polyominoSize) + "minos.bin";
return true;
}