diff --git a/src/Pieces/Piece.cpp b/src/Pieces/Piece.cpp index 431c818..bfff2f9 100644 --- a/src/Pieces/Piece.cpp +++ b/src/Pieces/Piece.cpp @@ -9,7 +9,7 @@ #include -Piece::Piece(const Polyomino& polyomino, Block blockType) : +Piece::Piece(Polyomino&& polyomino, Block blockType) : polyomino(polyomino), blockType(blockType), rotationState(NONE), diff --git a/src/Pieces/Piece.h b/src/Pieces/Piece.h index 99146f5..04a7074 100644 --- a/src/Pieces/Piece.h +++ b/src/Pieces/Piece.h @@ -22,7 +22,7 @@ class Piece { /** * Creates a piece with a specified shape and block type */ - Piece(const Polyomino& piece, Block blockType); + Piece(Polyomino&& piece, Block blockType); /** * Rotates the piece in the specified direction diff --git a/src/Pieces/PiecesFiles.cpp b/src/Pieces/PiecesFiles.cpp index 77c701a..f53b644 100644 --- a/src/Pieces/PiecesFiles.cpp +++ b/src/Pieces/PiecesFiles.cpp @@ -50,11 +50,12 @@ bool PiecesFiles::savePieces(int polyominoSize, std::vector& polyomin std::uint8_t infoByte = (isConvex << 7) + (hasHole << 6) + polyomino.getLength(); buffer << infoByte; + const int bitsNeeded = polyomino.getLength() * polyomino.getLength(); + const int longsNeeded = bitsNeeded / 64 + 1; + // write the positions of the piece - std::uint8_t positionByte; - for (const Position position : polyomino.getPositions()) { - positionByte = (position.x << 4) + position.y; - buffer << positionByte; + for (int i = 0; i < longsNeeded; i++) { + buffer << polyomino.getPositionsData()[i]; } } @@ -91,11 +92,11 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector& pieces, std: nextPieceBlockType(pieceBlock); } - char convexMask = 0b1000'0000; - char holeMask = 0b0100'0000; - char lengthMask = 0b0011'1111; - char xMask = 0b1111'0000; - char yMask = 0b0000'1111; + constexpr char convexMask = 0b1000'0000; + constexpr char holeMask = 0b0100'0000; + constexpr char lengthMask = 0b0011'1111; + constexpr char xMask = 0b1111'0000; + constexpr char yMask = 0b0000'1111; std::uint8_t infoByte; int i = 0; @@ -108,18 +109,17 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector& pieces, std: bool hasHole = (infoByte & holeMask) >> 6; int length = (infoByte & lengthMask); + const int bitsNeeded = length * length; + const int longsNeeded = bitsNeeded / 64 + 1; + // 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)); + Polyomino::PolyominoData polyominoData{}; + for (int i = 0; i < longsNeeded; i++) { + buffer >> polyominoData[i]; } // create piece - Piece readPiece(Polyomino(std::move(piecePositions), length), pieceBlock); + Piece readPiece(Polyomino(std::move(polyominoData), length), pieceBlock); nextPieceBlockType(pieceBlock); pieces.push_back(readPiece); diff --git a/src/Pieces/Polyomino.cpp b/src/Pieces/Polyomino.cpp index 3e4fd1c..45d9e5d 100644 --- a/src/Pieces/Polyomino.cpp +++ b/src/Pieces/Polyomino.cpp @@ -31,38 +31,6 @@ Polyomino::Polyomino(std::set&& positions) { this->positions = std::move(temp.positions); } -Polyomino::Polyomino(std::set&& positions, std::int8_t length) : positions(), length(length){ - for (Position position : positions) { - insert(position); - } -} - -Polyomino::Polyomino(PolyominoData&& positions) : positions(positions) { - int minX = INT_MAX; - int maxX = INT_MIN; - int minY = INT_MAX; - int maxY = INT_MIN; - - // tout s'appelle positions, osekour ! - std::vector tempPositions = getPositions(); - - for (const Position position : tempPositions) { - if (position.x < minX) minX = position.x; - if (position.x > maxX) maxX = position.x; - if (position.y < minY) minY = position.y; - if (position.y > maxY) maxY = position.y; - } - - this->length = std::max(maxX - minX + 1, maxY - minY + 1); - - // we normalize here instead of calling this->normalize() to reduce the number of calculations for the generation algorithm - Polyomino temp(PolyominoData{}, this->length); - for (Position position : tempPositions) { - temp.insert(Position(position.x - minX, position.y - minY)); - } - this->positions = std::move(temp.positions); -} - Polyomino::Polyomino(PolyominoData&& positions, std::int8_t length) : positions(std::move(positions)), length(length) { @@ -79,7 +47,7 @@ void Polyomino::normalize() { if (position.y < minY) minY = position.y; } - Polyomino temp(PolyominoData{}, this->length); + Polyomino temp({}, this->length); for (const Position position : tempPositions) { temp.insert(Position(position.x - minX, position.y - minY)); } @@ -87,7 +55,7 @@ void Polyomino::normalize() { } void Polyomino::rotateCW() { - Polyomino temp(PolyominoData{}, this->length); + Polyomino temp({}, this->length); for (const Position position : getPositions()) { temp.insert(Position(position.y, (length - 1) - (position.x))); } @@ -95,7 +63,7 @@ void Polyomino::rotateCW() { } void Polyomino::rotate180() { - Polyomino temp(PolyominoData{}, this->length); + Polyomino temp({}, this->length); for (const Position position : getPositions()) { temp.insert(Position((length - 1) - (position.x), (length - 1) - (position.y))); } @@ -103,7 +71,7 @@ void Polyomino::rotate180() { } void Polyomino::rotateCCW() { - Polyomino temp(PolyominoData{}, this->length); + Polyomino temp({}, this->length); for (const Position position : getPositions()) { temp.insert(Position((length - 1) - (position.y), position.x)); } @@ -200,7 +168,7 @@ void Polyomino::goToSpawnPosition() { } // center the piece with an up bias - Polyomino temp(PolyominoData{}, this->length); + Polyomino temp({}, this->length); for (const Position position : tempPositions) { temp.insert(Position((position.x - minX) + (verticalEmptyLines / 2), (position.y - minY) + ((horizontalEmptyLines + 1) / 2))); } @@ -298,7 +266,7 @@ void Polyomino::tryToInsertPosition(std::set& emptyPositions, const Po tryToInsertPosition(emptyPositions, Position(candidate.x - 1, candidate.y)); } -const PolyominoData& Polyomino::getPositionsData() const { +const Polyomino::PolyominoData& Polyomino::getPositionsData() const { return this->positions; } @@ -368,4 +336,11 @@ void Polyomino::insert(const Position& position) { int longIndex = posIndex / (sizeof(std::uint64_t) * 8); int bitIndex = posIndex % (sizeof(std::uint64_t) * 8); this->positions[longIndex] |= static_cast(1) << (sizeof(std::uint64_t) * 8 - bitIndex); +} + +void Polyomino::erase(const Position& position) { + int posIndex = position.y * this->length + position.x; + int longIndex = posIndex / (sizeof(std::uint64_t) * 8); + int bitIndex = posIndex % (sizeof(std::uint64_t) * 8); + this->positions[longIndex] &= ~(static_cast(1) << (sizeof(std::uint64_t) * 8 - bitIndex)); } \ No newline at end of file diff --git a/src/Pieces/Polyomino.h b/src/Pieces/Polyomino.h index 32eabac..c1c2086 100644 --- a/src/Pieces/Polyomino.h +++ b/src/Pieces/Polyomino.h @@ -7,30 +7,29 @@ #include #include -using PolyominoData = std::array; /** * A mathematical object consisting of touching squares on a 2D grid */ class Polyomino { + public: + static const std::size_t POLYOMINO_DATA_SIZE = 4; + using PolyominoData = std::array; + private: PolyominoData positions; // the squares composing the polyomino, stored in binary. MSB is downleft std::int8_t length; // the size of the smallest square box in which the polyomino can fit on any rotation - + public: - /** - * Creates a polyomino with the specified positions and normalizes it, wheter it is actually a polyonimo is not checked - */ - Polyomino(PolyominoData&& positions); - /** * Creates a polyomino with the specified positions and length, wheter it is actually a polyonimo of this length is not checked */ Polyomino(PolyominoData&& positions, std::int8_t length); - // this is temporary. They are here for compatibility reasons for now + /** + * Creates a polyomino with the specified positions and normalizes it, wheter it is actually a polyonimo is not checked + */ Polyomino(std::set&& positions); - Polyomino(std::set&& positions, std::int8_t length); /** * Translates the polyomino to the lowest unsigned values (lower row on y = 0, and left-most column on x = 0) @@ -127,9 +126,13 @@ class Polyomino { */ bool contains(const Position& position) const; - private: /** * @brief Insert a square at the position */ void insert(const Position& position); + + /** + * @brief Removes a square at the position + */ + void erase(const Position& position); };