129 lines
3.6 KiB
C++
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 = ((unsigned char) 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;
|
|
}
|