#include "PiecesFiles.h" #include "Generator.h" #include "Piece.h" #include #include #include #include #include #include #include "../Common/Compression.h" #include "../Utils/AssetManager.h" PiecesFiles::PiecesFiles() { } bool PiecesFiles::savePieces(int polyominoSize) const { std::string filePath; if (!this->getFilePath(polyominoSize, filePath)) { return false; } Generator generator; std::vector polyominoes = generator.generatePolyominoes(polyominoSize); return this->savePieces(polyominoSize, polyominoes); } bool PiecesFiles::savePieces(int polyominoSize, std::vector& 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& pieces, std::vector& convexPieces, std::vector& holelessPieces, std::vector& 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 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(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 { auto dataFolderPath = AssetManager::getResourcePath("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")).string(); return true; }