begin optimize Generator
Some checks failed
Linux arm64 / Build (push) Failing after 2m4s

This commit is contained in:
2025-07-19 23:39:22 +02:00
parent d5b51213c8
commit 46b9b8dd65
8 changed files with 158 additions and 59 deletions

View File

@@ -345,7 +345,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
// print only the position were the active piece is
for (int y = gameboard.activePiecePosition.y + gameboard.activePiece->getLength() - 1; y >= gameboard.board.getBaseHeight(); y--) {
for (int x = 0; x < gameboard.board.getWidth(); x++) {
bool hasActivePiece = gameboard.activePiece->getPositions().contains(Position(x, y) - gameboard.activePiecePosition);
bool hasActivePiece = gameboard.activePiece->containsSquare(Position(x, y) - gameboard.activePiecePosition);
if (hasActivePiece) {
os << "*";
}
@@ -361,7 +361,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
Block pieceBlockType = (gameboard.activePiece == nullptr) ? NOTHING : gameboard.activePiece->getBlockType();
for (int y = gameboard.board.getBaseHeight() - 1; y >= 0; y--) {
for (int x = 0; x < gameboard.board.getWidth(); x++) {
bool hasActivePiece = (gameboard.activePiece == nullptr) ? false : gameboard.activePiece->getPositions().contains(Position(x, y) - gameboard.activePiecePosition);
bool hasActivePiece = (gameboard.activePiece == nullptr) ? false : gameboard.activePiece->containsSquare(Position(x, y) - gameboard.activePiecePosition);
// the active piece takes visual priority over the board
if (hasActivePiece) {

View File

@@ -196,7 +196,7 @@ void GamePlayingAppMenu::drawFrame() const {
for (int y = 0; y < this->game.getNextPieces().at(i).getLength(); y++) {
for (int x = 0; x < this->game.getNextPieces().at(i).getLength(); x++) {
sf::RectangleShape cell(nextCellSize);
if (this->game.getNextPieces().at(i).getPositions().contains(Position(x, y))) {
if (this->game.getNextPieces().at(i).containsSquare(Position(x, y))) {
cell.setFillColor(pieceColor);
lowestRank = y;
}
@@ -223,7 +223,7 @@ void GamePlayingAppMenu::drawFrame() const {
for (int y = 0; y < this->game.getHeldPiece()->getLength(); y++) {
for (int x = 0; x < this->game.getHeldPiece()->getLength(); x++) {
sf::RectangleShape cell(holdCellSize);
if (this->game.getHeldPiece()->getPositions().contains(Position(x, y))) {
if (this->game.getHeldPiece()->containsSquare(Position(x, y))) {
cell.setFillColor(color);
}
else {

View File

@@ -29,7 +29,7 @@ std::vector<Polyomino>&& Generator::generatePolyominoes(int polyominoSize) {
void Generator::generate(int polyominoSize, int lastAddedPositionNumber, int nextAvaibleNumber, std::map<Position, int> candidatePositions) {
// recursion stop
if (polyominoSize == this->currentTestedShape.size()) {
Polyomino candidate(this->currentTestedShape);
Polyomino candidate(std::move(this->currentTestedShape));
// we sort the rotations of the polyominoes
std::vector<Polyomino> candidateRotations;

View File

@@ -11,9 +11,9 @@
Piece::Piece(const Polyomino& polyomino, Block blockType) :
polyomino(polyomino),
blockType(blockType) {
this->rotationState = NONE;
blockType(blockType),
rotationState(NONE),
positions(polyomino.getPositions()) {
}
void Piece::rotate(Rotation rotation) {
@@ -25,6 +25,7 @@ void Piece::rotate(Rotation rotation) {
this->polyomino.rotateCCW();
this->rotationState += rotation;
this->positions = polyomino.getPositions();
}
void Piece::defaultRotation() {
@@ -36,10 +37,11 @@ void Piece::defaultRotation() {
this->polyomino.rotateCW();
this->rotationState = NONE;
this->positions = polyomino.getPositions();
}
const std::set<Position>& Piece::getPositions() const {
return this->polyomino.getPositions();
const std::vector<Position>& Piece::getPositions() const {
return this->positions;
}
int Piece::getLength() const {
@@ -54,3 +56,7 @@ std::ostream& operator<<(std::ostream& os, const Piece& piece) {
os << getConsoleColorCode(piece.blockType) << piece.polyomino << getResetConsoleColorCode();
return os;
}
bool Piece::containsSquare(const Position& position) const {
return polyomino.contains(position);
}

View File

@@ -16,6 +16,7 @@ class Piece {
Polyomino polyomino; // a polyomino representing the piece, (0, 0) is downleft
Block blockType; // the block type of the piece
Rotation rotationState; // the current rotation of the piece
std::vector<Position> positions; // cache positions for easier use (particularly UI)
public:
/**
@@ -36,7 +37,13 @@ class Piece {
/**
* @return The list of positions of the piece
*/
const std::set<Position>& getPositions() const;
const std::vector<Position>& getPositions() const;
/**
* @param the position of the square
* @return false if there is a hole
*/
bool containsSquare(const Position& position) const;
/**
* @return The length of the piece

View File

@@ -119,7 +119,7 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
}
// create piece
Piece readPiece(Polyomino(piecePositions, length), pieceBlock);
Piece readPiece(Polyomino(std::move(piecePositions), length), pieceBlock);
nextPieceBlockType(pieceBlock);
pieces.push_back(readPiece);

View File

@@ -9,8 +9,7 @@
#include <algorithm>
#include <utility>
Polyomino::Polyomino(const std::set<Position>& positions) {
Polyomino::Polyomino(std::set<Position>&& positions) {
int minX = INT_MAX;
int maxX = INT_MIN;
int minY = INT_MAX;
@@ -25,55 +24,90 @@ Polyomino::Polyomino(const std::set<Position>& positions) {
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
std::set<Position> newPositions;
Polyomino temp(PolyominoData{}, this->length);
for (Position position : positions) {
newPositions.insert(Position(position.x - minX, position.y - minY));
temp.insert(Position(position.x - minX, position.y - minY));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
Polyomino::Polyomino(const std::set<Position>& positions, std::int8_t length) :
positions(positions),
Polyomino::Polyomino(std::set<Position>&& 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<Position> 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) {
}
void Polyomino::normalize() {
int minX = INT_MAX;
int minY = INT_MAX;
for (const Position position : this->positions) {
std::vector<Position> tempPositions = getPositions();
for (const Position position : tempPositions) {
if (position.x < minX) minX = position.x;
if (position.y < minY) minY = position.y;
}
std::set<Position> newPositions;
for (const Position position : this->positions) {
newPositions.insert(Position(position.x - minX, position.y - minY));
Polyomino temp(PolyominoData{}, this->length);
for (const Position position : tempPositions) {
temp.insert(Position(position.x - minX, position.y - minY));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
void Polyomino::rotateCW() {
std::set<Position> newPositions;
for (const Position position : this->positions) {
newPositions.insert(Position(position.y, (length - 1) - (position.x)));
Polyomino temp(PolyominoData{}, this->length);
for (const Position position : getPositions()) {
temp.insert(Position(position.y, (length - 1) - (position.x)));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
void Polyomino::rotate180() {
std::set<Position> newPositions;
for (const Position position : this->positions) {
newPositions.insert(Position((length - 1) - (position.x), (length - 1) - (position.y)));
Polyomino temp(PolyominoData{}, this->length);
for (const Position position : getPositions()) {
temp.insert(Position((length - 1) - (position.x), (length - 1) - (position.y)));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
void Polyomino::rotateCCW() {
std::set<Position> newPositions;
for (const Position position : this->positions) {
newPositions.insert(Position((length - 1) - (position.y), position.x));
Polyomino temp(PolyominoData{}, this->length);
for (const Position position : getPositions()) {
temp.insert(Position((length - 1) - (position.y), position.x));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
void Polyomino::goToSpawnPosition() {
@@ -89,7 +123,7 @@ void Polyomino::goToSpawnPosition() {
}
// calculates amount of squares per rows and columns
for (const Position position : this->positions) {
for (const Position position : getPositions()) {
linesCompleteness.at(0).at(position.y) += 1; // 0 = bottom to top = no rotation
linesCompleteness.at(1).at((length - 1) - position.x) += 1; // 1 = right to left = CW
linesCompleteness.at(2).at((length - 1) - position.y) += 1; // 2 = top to bottom = 180
@@ -155,20 +189,22 @@ void Polyomino::goToSpawnPosition() {
if (sideToBeOn % 2 == 1) {
std::swap(verticalEmptyLines, horizontalEmptyLines);
}
std::vector<Position> tempPositions = getPositions();
int minX = INT_MAX;
int minY = INT_MAX;
for (const Position position : this->positions) {
for (const Position position : tempPositions) {
if (position.x < minX) minX = position.x;
if (position.y < minY) minY = position.y;
}
// center the piece with an up bias
std::set<Position> newPositions;
for (const Position position : positions) {
newPositions.insert(Position((position.x - minX) + (verticalEmptyLines / 2), (position.y - minY) + ((horizontalEmptyLines + 1) / 2)));
Polyomino temp(PolyominoData{}, this->length);
for (const Position position : tempPositions) {
temp.insert(Position((position.x - minX) + (verticalEmptyLines / 2), (position.y - minY) + ((horizontalEmptyLines + 1) / 2)));
}
this->positions = std::move(newPositions);
this->positions = std::move(temp.positions);
}
void Polyomino::checkForFlattestSide(const std::vector<std::vector<int>>& linesCompleteness, bool currentFlattestSides[4], int& sideToBeOn, bool checkLeftSide) const {
@@ -216,7 +252,7 @@ bool Polyomino::isConvex() const {
bool startedColumn = false;
bool completedColumn = false;
for (int i = 0; i < this->length; i++) {
if (this->positions.contains(Position(i, j))) {
if (this->contains(Position(i, j))) {
if (completedLine) return false;
else startedLine = true;
}
@@ -224,7 +260,7 @@ bool Polyomino::isConvex() const {
if (startedLine) completedLine = true;
}
if (this->positions.contains(Position(j, i))) {
if (this->contains(Position(j, i))) {
if (completedColumn) return false;
else startedColumn = true;
}
@@ -252,7 +288,7 @@ bool Polyomino::hasHole() const {
void Polyomino::tryToInsertPosition(std::set<Position>& emptyPositions, const Position& candidate) const {
if (candidate.x >= this->length || candidate.x < 0 || candidate.y >= this->length || candidate.y < 0) return;
if (this->positions.contains(candidate) || emptyPositions.contains(candidate)) return;
if (this->contains(candidate) || emptyPositions.contains(candidate)) return;
// if it's a new empty square, try its neighbors
emptyPositions.insert(candidate);
@@ -262,10 +298,25 @@ void Polyomino::tryToInsertPosition(std::set<Position>& emptyPositions, const Po
tryToInsertPosition(emptyPositions, Position(candidate.x - 1, candidate.y));
}
const std::set<Position>& Polyomino::getPositions() const {
const PolyominoData& Polyomino::getPositionsData() const {
return this->positions;
}
std::vector<Position> Polyomino::getPositions() const {
std::vector<Position> result;
for (int y = 0; y < this->length; y++) {
for (int x = 0; x < this->length; x++) {
int posIndex = y * this->length + x;
int longIndex = posIndex / (sizeof(std::uint64_t) * 8);
int bitIndex = posIndex % (sizeof(std::uint64_t) * 8);
if (this->positions[longIndex] & static_cast<std::uint64_t>(1) << (sizeof(std::uint64_t) * 8 - bitIndex)) {
result.push_back(Position(x, y));
}
}
}
return result;
}
int Polyomino::getLength() const {
return this->length;
}
@@ -277,13 +328,12 @@ int Polyomino::getPolyominoSize() const {
bool Polyomino::operator<(const Polyomino& other) const {
if (this->length != other.length) return this->length < other.length;
for (int y = this->length - 1; y >= 0; y--) {
for (int x = 0; x < this->length; x++) {
bool hasThisPosition = this->positions.contains(Position(x, y));
bool hasOtherPosition = other.positions.contains(Position(x, y));
if (hasThisPosition != hasOtherPosition) return hasThisPosition;
for (int i = 0; i < this->positions.size(); i++) {
if (this->positions[i] != other.positions[i]) {
return this->positions[i] < other.positions[i];
}
}
return false;
}
@@ -294,7 +344,7 @@ bool Polyomino::operator==(const Polyomino& other) const {
std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino) {
for (int y = polyomino.length - 1; y >= 0; y--) {
for (int x = 0; x < polyomino.length; x++) {
if (polyomino.positions.contains(Position(x, y))) {
if (polyomino.contains(Position(x, y))) {
os << "*";
}
else {
@@ -305,3 +355,17 @@ std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino) {
}
return os;
}
bool Polyomino::contains(const Position& position) const {
int posIndex = position.y * this->length + position.x;
int longIndex = posIndex / (sizeof(std::uint64_t) * 8);
int bitIndex = posIndex % (sizeof(std::uint64_t) * 8);
return this->positions[longIndex] & static_cast<std::uint64_t>(1) << (sizeof(std::uint64_t) * 8 - bitIndex);
}
void Polyomino::insert(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<std::uint64_t>(1) << (sizeof(std::uint64_t) * 8 - bitIndex);
}

View File

@@ -5,26 +5,32 @@
#include <vector>
#include <set>
#include <iostream>
#include <array>
using PolyominoData = std::array<std::uint64_t, 4>;
/**
* A mathematical object consisting of touching squares on a 2D grid
*/
class Polyomino {
private:
std::set<Position> positions; // the squares composing the polyomino, (0,0) is downleft
std::int8_t length; // the size of the smallest square box in which the polyomino can fit on any rotation
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(const std::set<Position>& positions);
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(const std::set<Position>& positions, std::int8_t length);
Polyomino(PolyominoData&& positions, std::int8_t length);
// this is temporary. They are here for compatibility reasons for now
Polyomino(std::set<Position>&& positions);
Polyomino(std::set<Position>&& 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)
@@ -70,7 +76,7 @@ class Polyomino {
*/
bool hasHole() const;
private :
private:
/**
* Auxiliary method of hasHole()
*/
@@ -78,9 +84,14 @@ class Polyomino {
public:
/**
* @return The positions of the polyomino
* @return The positions data of the polyomino
*/
const std::set<Position>& getPositions() const;
const PolyominoData& getPositionsData() const;
/**
* @return The positions of the polyomino (deduces it from the binary representation)
*/
std::vector<Position> getPositions() const;
/**
* @return The length of the polyomino
@@ -110,4 +121,15 @@ class Polyomino {
* @return A reference to the output stream
*/
friend std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino);
/**
* @return True if it contains the position
*/
bool contains(const Position& position) const;
private:
/**
* @brief Insert a square at the position
*/
void insert(const Position& position);
};