Files
jminos/src/Pieces/PiecesFiles.cpp
2025-03-05 19:02:51 +01:00

129 lines
3.6 KiB
C++

#include "PiecesFiles.h"
#include "Generator.h"
#include "Piece.h"
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <algorithm>
PiecesFiles::PiecesFiles() {
}
bool PiecesFiles::savePieces(int polyominoSize) const {
std::string filePath;
if (!this->getFilePath(polyominoSize, filePath)) {
return false;
}
std::ofstream piecesFile(filePath, std::ios::trunc | std::ios::binary);
if (!piecesFile.good()) {
return false;
}
Generator generator;
std::vector<Polyomino> nMinos = generator.generatePolyominoes(polyominoSize);
// sorting the polyominoes is done after setting spawn position to ensure the order is always the same
for (Polyomino& nMino : nMinos) {
nMino.goToSpawnPosition();
}
std::sort(nMinos.begin(), nMinos.end());
for (const Polyomino& nMino : nMinos) {
// write the characteristics of the piece
char infoByte = (nMino.isConvex() << 7) + (nMino.hasHole() << 6) + nMino.getLength();
piecesFile.write(&infoByte, 1);
// write the positions of the piece
char positionByte;
for (Position position : nMino.getPositions()) {
positionByte = (position.x << 4) + position.y;
piecesFile.write(&positionByte, 1);
}
}
return true;
}
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;
}
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;
char infoByte;
int i = 0;
while (piecesFile.get(infoByte)) {
if (piecesFile.eof()) break;
// read piece infos
bool isConvex = (infoByte & convexMask) >> 7;
bool hasHole = (infoByte & holeMask) >> 6;
int length = (infoByte & lengthMask);
// read positions
std::set<Position> piecePositions;
char positionByte;
for (int i = 0; i < polyominoSize; i++) {
piecesFile.get(positionByte);
int x = (positionByte & xMask) >> 4;
int y = positionByte & yMask;
piecePositions.insert(Position{x, y});
}
// create piece
Piece readPiece(Polyomino(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::is_directory(dataFolderPath)) {
return false;
}
filePath = dataFolderPath + std::to_string(polyominoSize) + "minos.bin";
return true;
}