#include "PiecesFiles.h" #include "Generator.h" #include "Piece.h" #include #include #include #include #include #include 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 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& pieces, std::vector& convexPieces, std::vector& holelessPieces, std::vector& 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 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; }