Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
de63cd22b6
|
|||
| 07ba9619ed | |||
| 4095103843 | |||
| ecc035c972 | |||
| dd6da58642 | |||
| a3ef52c7a1 | |||
| 72e9f420ab | |||
| 46b9b8dd65 | |||
| d5b51213c8 |
@@ -35,7 +35,7 @@ Bag::Bag(const std::shared_ptr<PiecesList>& piecesList) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& piece : this->selectedPieces) {
|
for (const auto& piece : this->selectedPieces) {
|
||||||
int pieceSize = this->piecesList->lookAtPiece(piece).getPositions().size();
|
int pieceSize = this->piecesList->lookAtPiece(piece).getPositions().getSize();
|
||||||
this->currentBags.at(pieceSize).push_back(piece);
|
this->currentBags.at(pieceSize).push_back(piece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ Board::Board(int width, int height) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::changeBlock(const Position& position, Block block) {
|
void Board::changeBlock(const Position& position, Block block) {
|
||||||
if (position.x < 0 || position.x >= this->width || position.y < 0) return;
|
if (position.x < 0 || static_cast<unsigned>(position.x) >= this->width || position.y < 0) return;
|
||||||
|
|
||||||
// resize the grid if needed
|
// resize the grid if needed
|
||||||
if (position.y >= this->grid.size()) {
|
if (static_cast<unsigned>(position.y) >= this->grid.size()) {
|
||||||
for (int j = this->grid.size(); j <= position.y; j++) {
|
for (int j = this->grid.size(); j <= position.y; j++) {
|
||||||
this->grid.push_back(this->emptyRow);
|
this->grid.push_back(this->emptyRow);
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ void Board::changeBlock(const Position& position, Block block) {
|
|||||||
|
|
||||||
void Board::insertRow(int height, int holePosition, Block blockType) {
|
void Board::insertRow(int height, int holePosition, Block blockType) {
|
||||||
std::vector<Block> insertedRow;
|
std::vector<Block> insertedRow;
|
||||||
for (int i = 0; i < this->width; i++) {
|
for (unsigned i = 0; i < this->width; i++) {
|
||||||
if (i == holePosition) {
|
if (i == holePosition) {
|
||||||
insertedRow.push_back(NOTHING);
|
insertedRow.push_back(NOTHING);
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ int Board::clearRows() {
|
|||||||
int clearedLines = 0;
|
int clearedLines = 0;
|
||||||
for (int j = this->grid.size() - 1; j >= 0; j--) {
|
for (int j = this->grid.size() - 1; j >= 0; j--) {
|
||||||
bool lineIsFull = true;
|
bool lineIsFull = true;
|
||||||
int i = 0;
|
unsigned i = 0;
|
||||||
while (lineIsFull && (i < width)) {
|
while (lineIsFull && (i < width)) {
|
||||||
if (this->grid.at(j).at(i) == NOTHING) {
|
if (this->grid.at(j).at(i) == NOTHING) {
|
||||||
lineIsFull = false;
|
lineIsFull = false;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class Board {
|
|||||||
private:
|
private:
|
||||||
std::vector<std::vector<Block>> grid; // the grid, (0,0) is downleft
|
std::vector<std::vector<Block>> grid; // the grid, (0,0) is downleft
|
||||||
std::vector<Block> emptyRow; // an empty row of blocks
|
std::vector<Block> emptyRow; // an empty row of blocks
|
||||||
int width; // the width of the grid
|
unsigned width; // the width of the grid
|
||||||
int height; // the base height of the grid, which can extend indefinitely
|
unsigned height; // the base height of the grid, which can extend indefinitely
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void GameBoard::initialize() {
|
|||||||
bool GameBoard::moveLeft() {
|
bool GameBoard::moveLeft() {
|
||||||
this->movedLeftLast = true;
|
this->movedLeftLast = true;
|
||||||
|
|
||||||
if (this->activePieceInWall(Position{-1, 0})) {
|
if (this->activePieceInWall(Position(-1, 0))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -57,7 +57,7 @@ bool GameBoard::moveLeft() {
|
|||||||
bool GameBoard::moveRight() {
|
bool GameBoard::moveRight() {
|
||||||
this->movedLeftLast = false;
|
this->movedLeftLast = false;
|
||||||
|
|
||||||
if (this->activePieceInWall(Position{1, 0})) {
|
if (this->activePieceInWall(Position(1, 0))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -68,7 +68,7 @@ bool GameBoard::moveRight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GameBoard::moveDown() {
|
bool GameBoard::moveDown() {
|
||||||
if (this->activePieceInWall(Position{0, -1})) {
|
if (this->activePieceInWall(Position(0, -1))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -100,10 +100,10 @@ bool GameBoard::rotate(Rotation rotation) {
|
|||||||
for (Position position : stored.getPositions()) {
|
for (Position position : stored.getPositions()) {
|
||||||
Position positionInGrid(position + this->activePiecePosition);
|
Position positionInGrid(position + this->activePiecePosition);
|
||||||
safePositions.insert(positionInGrid);
|
safePositions.insert(positionInGrid);
|
||||||
safePositions.insert(positionInGrid + Position{0, 1});
|
safePositions.insert(positionInGrid + Position(0, 1));
|
||||||
safePositions.insert(positionInGrid + Position{1, 0});
|
safePositions.insert(positionInGrid + Position(1, 0));
|
||||||
safePositions.insert(positionInGrid + Position{0, -1});
|
safePositions.insert(positionInGrid + Position(0, -1));
|
||||||
safePositions.insert(positionInGrid + Position{-1, 0});
|
safePositions.insert(positionInGrid + Position(-1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// first try kicking the piece down
|
// first try kicking the piece down
|
||||||
@@ -147,18 +147,18 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Position>& safePos
|
|||||||
// we first check the side to which the player moved last
|
// we first check the side to which the player moved last
|
||||||
if (movedLeftLast) {
|
if (movedLeftLast) {
|
||||||
if (overlapsLeft) {
|
if (overlapsLeft) {
|
||||||
if (this->tryFittingKickedPiece(safePositions, Position({-i, j}), overlapsLeft)) return true;
|
if (this->tryFittingKickedPiece(safePositions, Position(-i, j), overlapsLeft)) return true;
|
||||||
}
|
}
|
||||||
if (overlapsRight) {
|
if (overlapsRight) {
|
||||||
if (this->tryFittingKickedPiece(safePositions, Position({+i, j}), overlapsRight)) return true;
|
if (this->tryFittingKickedPiece(safePositions, Position(+i, j), overlapsRight)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (overlapsRight) {
|
if (overlapsRight) {
|
||||||
if (this->tryFittingKickedPiece(safePositions, Position({+i, j}), overlapsRight)) return true;
|
if (this->tryFittingKickedPiece(safePositions, Position(+i, j), overlapsRight)) return true;
|
||||||
}
|
}
|
||||||
if (overlapsLeft) {
|
if (overlapsLeft) {
|
||||||
if (this->tryFittingKickedPiece(safePositions, Position({-i, j}), overlapsLeft)) return true;
|
if (this->tryFittingKickedPiece(safePositions, Position(-i, j), overlapsLeft)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,11 +265,11 @@ bool GameBoard::activePieceInWall(const Position& shift) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GameBoard::touchesGround() const {
|
bool GameBoard::touchesGround() const {
|
||||||
return this->activePieceInWall(Position{0, -1});
|
return this->activePieceInWall(Position(0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Position GameBoard::lowestPosition() const {
|
Position GameBoard::lowestPosition() const {
|
||||||
Position shift = Position{0, -1};
|
Position shift = Position(0, -1);
|
||||||
while (!activePieceInWall(shift)) {
|
while (!activePieceInWall(shift)) {
|
||||||
shift.y -= 1;
|
shift.y -= 1;
|
||||||
}
|
}
|
||||||
@@ -278,8 +278,8 @@ Position GameBoard::lowestPosition() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LineClear GameBoard::lockPiece() {
|
LineClear GameBoard::lockPiece() {
|
||||||
bool isLockedInPlace = (this->activePieceInWall(Position{0, 1}) && this->activePieceInWall(Position{1, 0})
|
bool isLockedInPlace = (this->activePieceInWall(Position(0, 1)) && this->activePieceInWall(Position(1, 0))
|
||||||
&& this->activePieceInWall(Position{-1, 0}) && this->activePieceInWall(Position{0, -1}));
|
&& this->activePieceInWall(Position(-1, 0)) && this->activePieceInWall(Position(0, -1)));
|
||||||
|
|
||||||
for (Position position : this->activePiece->getPositions()) {
|
for (Position position : this->activePiece->getPositions()) {
|
||||||
this->board.changeBlock(position + this->activePiecePosition, this->activePiece->getBlockType());
|
this->board.changeBlock(position + this->activePiecePosition, this->activePiece->getBlockType());
|
||||||
@@ -345,7 +345,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
|||||||
// print only the position were the active piece is
|
// 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 y = gameboard.activePiecePosition.y + gameboard.activePiece->getLength() - 1; y >= gameboard.board.getBaseHeight(); y--) {
|
||||||
for (int x = 0; x < gameboard.board.getWidth(); x++) {
|
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) {
|
if (hasActivePiece) {
|
||||||
os << "*";
|
os << "*";
|
||||||
}
|
}
|
||||||
@@ -361,7 +361,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
|||||||
Block pieceBlockType = (gameboard.activePiece == nullptr) ? NOTHING : gameboard.activePiece->getBlockType();
|
Block pieceBlockType = (gameboard.activePiece == nullptr) ? NOTHING : gameboard.activePiece->getBlockType();
|
||||||
for (int y = gameboard.board.getBaseHeight() - 1; y >= 0; y--) {
|
for (int y = gameboard.board.getBaseHeight() - 1; y >= 0; y--) {
|
||||||
for (int x = 0; x < gameboard.board.getWidth(); x++) {
|
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
|
// the active piece takes visual priority over the board
|
||||||
if (hasActivePiece) {
|
if (hasActivePiece) {
|
||||||
@@ -369,7 +369,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
|||||||
os << "*";
|
os << "*";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Block block = gameboard.board.getBlock(Position{x, y});
|
Block block = gameboard.board.getBlock(Position(x, y));
|
||||||
os << getConsoleColorCode(block);
|
os << getConsoleColorCode(block);
|
||||||
if (block != NOTHING) {
|
if (block != NOTHING) {
|
||||||
os << "*";
|
os << "*";
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class GameBoard {
|
|||||||
* Check if one of the active piece's positions shifted by a specified position would overlap with a set of positions
|
* Check if one of the active piece's positions shifted by a specified position would overlap with a set of positions
|
||||||
* @return If the shifted active piece overlaps with one of the position
|
* @return If the shifted active piece overlaps with one of the position
|
||||||
*/
|
*/
|
||||||
bool activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift = Position{0, 0}) const;
|
bool activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift = Position(0, 0)) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +103,7 @@ class GameBoard {
|
|||||||
* Checks if one of the active piece's positions touches a wall in the board
|
* Checks if one of the active piece's positions touches a wall in the board
|
||||||
* @return If the active piece is in a wall
|
* @return If the active piece is in a wall
|
||||||
*/
|
*/
|
||||||
bool activePieceInWall(const Position& shift = Position{0, 0}) const;
|
bool activePieceInWall(const Position& shift = Position(0, 0)) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks is the active piece as a wall directly below one of its position
|
* Checks is the active piece as a wall directly below one of its position
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ PiecesList::PiecesList() {
|
|||||||
this->pushBackEmptyVectors();
|
this->pushBackEmptyVectors();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PiecesList::loadPieces(int max_size) {
|
bool PiecesList::loadPieces(unsigned max_size) {
|
||||||
if (max_size < 1) return false;
|
if (max_size < 1) return false;
|
||||||
if (max_size <= this->highestLoadedSize) return true;
|
if (max_size <= this->highestLoadedSize) return true;
|
||||||
|
|
||||||
PiecesFiles piecesFiles;
|
PiecesFiles piecesFiles;
|
||||||
for (int i = this->highestLoadedSize + 1; i <= max_size; i++) {
|
for (unsigned i = this->highestLoadedSize + 1; i <= max_size; i++) {
|
||||||
if (!piecesFiles.loadPieces(i, this->loadedPieces.at(i), this->convexPieces.at(i), this->holelessPieces.at(i), this->otherPieces.at(i))) {
|
if (!piecesFiles.loadPieces(i, this->loadedPieces.at(i), this->convexPieces.at(i), this->holelessPieces.at(i), this->otherPieces.at(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -45,14 +45,14 @@ bool PiecesList::loadPieces(int max_size) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PiecesList::selectPiece(int size, int number) {
|
bool PiecesList::selectPiece(unsigned size, unsigned number) {
|
||||||
if (size < 1 || size > this->highestLoadedSize || number >= this->loadedPieces.at(size).size()) return false;
|
if (size < 1 || size > this->highestLoadedSize || number >= this->loadedPieces.at(size).size()) return false;
|
||||||
|
|
||||||
this->selectedPieces.push_back(std::pair<int, int>(size, number));
|
this->selectedPieces.push_back(std::pair<int, int>(size, number));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PiecesList::selectAllPieces(int size) {
|
bool PiecesList::selectAllPieces(unsigned size) {
|
||||||
if (size < 1 || size > this->highestLoadedSize) return false;
|
if (size < 1 || size > this->highestLoadedSize) return false;
|
||||||
|
|
||||||
for (int i = 0; i < this->loadedPieces.at(size).size(); i++) {
|
for (int i = 0; i < this->loadedPieces.at(size).size(); i++) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
class PiecesList {
|
class PiecesList {
|
||||||
private:
|
private:
|
||||||
int highestLoadedSize; // the highest size of pieces currently loaded
|
unsigned highestLoadedSize; // the highest size of pieces currently loaded
|
||||||
std::vector<std::vector<Piece>> loadedPieces; // every loaded pieces by size
|
std::vector<std::vector<Piece>> loadedPieces; // every loaded pieces by size
|
||||||
std::vector<std::vector<int>> convexPieces; // the list of convex loaded pieces by size
|
std::vector<std::vector<int>> convexPieces; // the list of convex loaded pieces by size
|
||||||
std::vector<std::vector<int>> holelessPieces; // the list of holeless loaded pieces by size
|
std::vector<std::vector<int>> holelessPieces; // the list of holeless loaded pieces by size
|
||||||
@@ -33,19 +33,19 @@ class PiecesList {
|
|||||||
* Makes the list load all pieces up to the specified size
|
* Makes the list load all pieces up to the specified size
|
||||||
* @return If all pieces up to the specified size are correctly loaded
|
* @return If all pieces up to the specified size are correctly loaded
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool loadPieces(int max_size);
|
[[nodiscard]] bool loadPieces(unsigned max_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the specified piece
|
* Selects the specified piece
|
||||||
* @return If the piece could be selected
|
* @return If the piece could be selected
|
||||||
*/
|
*/
|
||||||
bool selectPiece(int size, int number);
|
bool selectPiece(unsigned size, unsigned number);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects all pieces of the specified size
|
* Selects all pieces of the specified size
|
||||||
* @return If the pieces could be selected
|
* @return If the pieces could be selected
|
||||||
*/
|
*/
|
||||||
bool selectAllPieces(int size);
|
bool selectAllPieces(unsigned size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects all convex pieces of the specified size
|
* Selects all convex pieces of the specified size
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ void GamePlayingAppMenu::drawFrame() const {
|
|||||||
// board
|
// board
|
||||||
for (int y = this->game.getBoard().getBaseHeight() + 9; y >= 0; y--) {
|
for (int y = this->game.getBoard().getBaseHeight() + 9; y >= 0; y--) {
|
||||||
for (int x = 0; x < this->game.getBoard().getWidth(); x++) {
|
for (int x = 0; x < this->game.getBoard().getWidth(); x++) {
|
||||||
Block block = this->game.getBoard().getBlock(Position{x, y});
|
Block block = this->game.getBoard().getBlock(Position(x, y));
|
||||||
if (isBoardInvisible) block = NOTHING;
|
if (isBoardInvisible) block = NOTHING;
|
||||||
|
|
||||||
sf::RectangleShape cell(cellSize);
|
sf::RectangleShape cell(cellSize);
|
||||||
@@ -196,7 +196,7 @@ void GamePlayingAppMenu::drawFrame() const {
|
|||||||
for (int y = 0; y < this->game.getNextPieces().at(i).getLength(); y++) {
|
for (int y = 0; y < this->game.getNextPieces().at(i).getLength(); y++) {
|
||||||
for (int x = 0; x < this->game.getNextPieces().at(i).getLength(); x++) {
|
for (int x = 0; x < this->game.getNextPieces().at(i).getLength(); x++) {
|
||||||
sf::RectangleShape cell(nextCellSize);
|
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);
|
cell.setFillColor(pieceColor);
|
||||||
lowestRank = y;
|
lowestRank = y;
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ void GamePlayingAppMenu::drawFrame() const {
|
|||||||
for (int y = 0; y < this->game.getHeldPiece()->getLength(); y++) {
|
for (int y = 0; y < this->game.getHeldPiece()->getLength(); y++) {
|
||||||
for (int x = 0; x < this->game.getHeldPiece()->getLength(); x++) {
|
for (int x = 0; x < this->game.getHeldPiece()->getLength(); x++) {
|
||||||
sf::RectangleShape cell(holdCellSize);
|
sf::RectangleShape cell(holdCellSize);
|
||||||
if (this->game.getHeldPiece()->getPositions().contains(Position{x, y})) {
|
if (this->game.getHeldPiece()->containsSquare(Position(x, y))) {
|
||||||
cell.setFillColor(color);
|
cell.setFillColor(color);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -11,25 +11,25 @@
|
|||||||
Generator::Generator() {
|
Generator::Generator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Polyomino> Generator::generatePolyominoes(int polyominoSize) {
|
std::vector<Polyomino>&& Generator::generatePolyominoes(int polyominoSize) {
|
||||||
this->validPolyominoes.clear();
|
this->validPolyominoes.clear();
|
||||||
this->currentTestedShape.clear();
|
this->currentTestedShape.clear();
|
||||||
|
|
||||||
// a polyomino has at least 1 square
|
// a polyomino has at least 1 square
|
||||||
if (polyominoSize < 1) return this->validPolyominoes;
|
if (polyominoSize < 1) return std::move(this->validPolyominoes);
|
||||||
|
|
||||||
// always place the first cell at (0, 0)
|
// always place the first cell at (0, 0)
|
||||||
this->currentTestedShape.insert(Position{0, 0});
|
this->currentTestedShape.insert(Position(0, 0));
|
||||||
|
|
||||||
std::map<Position, int> candidatePositions;
|
std::map<Position, int> candidatePositions;
|
||||||
this->generate(polyominoSize, 0, 1, candidatePositions);
|
this->generate(polyominoSize, 0, 1, candidatePositions);
|
||||||
return this->validPolyominoes;
|
return std::move(this->validPolyominoes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generator::generate(int polyominoSize, int lastAddedPositionNumber, int nextAvaibleNumber, std::map<Position, int> candidatePositions) {
|
void Generator::generate(unsigned polyominoSize, int lastAddedPositionNumber, int nextAvaibleNumber, std::map<Position, int> candidatePositions) {
|
||||||
// recursion stop
|
// recursion stop
|
||||||
if (polyominoSize == this->currentTestedShape.size()) {
|
if (polyominoSize == this->currentTestedShape.size()) {
|
||||||
Polyomino candidate(this->currentTestedShape);
|
Polyomino candidate(std::move(this->currentTestedShape));
|
||||||
|
|
||||||
// we sort the rotations of the polyominoes
|
// we sort the rotations of the polyominoes
|
||||||
std::vector<Polyomino> candidateRotations;
|
std::vector<Polyomino> candidateRotations;
|
||||||
@@ -51,14 +51,14 @@ void Generator::generate(int polyominoSize, int lastAddedPositionNumber, int nex
|
|||||||
|
|
||||||
// generate the list of candidate positions
|
// generate the list of candidate positions
|
||||||
for (const Position position : this->currentTestedShape) {
|
for (const Position position : this->currentTestedShape) {
|
||||||
this->tryToAddCandidatePosition(Position{position.x, position.y + 1}, nextAvaibleNumber, candidatePositions);
|
this->tryToAddCandidatePosition(Position(position.x, position.y + 1), nextAvaibleNumber, candidatePositions);
|
||||||
this->tryToAddCandidatePosition(Position{position.x + 1, position.y}, nextAvaibleNumber, candidatePositions);
|
this->tryToAddCandidatePosition(Position(position.x + 1, position.y), nextAvaibleNumber, candidatePositions);
|
||||||
this->tryToAddCandidatePosition(Position{position.x, position.y - 1}, nextAvaibleNumber, candidatePositions);
|
this->tryToAddCandidatePosition(Position(position.x, position.y - 1), nextAvaibleNumber, candidatePositions);
|
||||||
this->tryToAddCandidatePosition(Position{position.x - 1, position.y}, nextAvaibleNumber, candidatePositions);
|
this->tryToAddCandidatePosition(Position(position.x - 1, position.y), nextAvaibleNumber, candidatePositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try adding a square only to positions with a higher number than the last one
|
// try adding a square only to positions with a higher number than the last one
|
||||||
for (const auto [key, val] : candidatePositions) {
|
for (const auto& [key, val] : candidatePositions) {
|
||||||
if (val > lastAddedPositionNumber) {
|
if (val > lastAddedPositionNumber) {
|
||||||
this->currentTestedShape.insert(key);
|
this->currentTestedShape.insert(key);
|
||||||
this->generate(polyominoSize, val, nextAvaibleNumber, (polyominoSize == this->currentTestedShape.size()) ? std::map<Position, int>() : candidatePositions);
|
this->generate(polyominoSize, val, nextAvaibleNumber, (polyominoSize == this->currentTestedShape.size()) ? std::map<Position, int>() : candidatePositions);
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ class Generator {
|
|||||||
* Generates the list of all one-sided polyominoes of the specified size
|
* Generates the list of all one-sided polyominoes of the specified size
|
||||||
* @return The list of polyominoes
|
* @return The list of polyominoes
|
||||||
*/
|
*/
|
||||||
std::vector<Polyomino> generatePolyominoes(int polyominoSize);
|
std::vector<Polyomino>&& generatePolyominoes(int polyominoSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Generates all one-sided polyominoes of the specified size using the current tested shape
|
* Generates all one-sided polyominoes of the specified size using the current tested shape
|
||||||
*/
|
*/
|
||||||
void generate(int polyominoSize, int lastAddedPositionNumber, int nextAvaibleNumber, std::map<Position, int> candidatePositions);
|
void generate(unsigned polyominoSize, int lastAddedPositionNumber, int nextAvaibleNumber, std::map<Position, int> candidatePositions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks wheter a candidate position can be added to the current tested shape
|
* Checks wheter a candidate position can be added to the current tested shape
|
||||||
|
|||||||
@@ -9,11 +9,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
Piece::Piece(const Polyomino& polyomino, Block blockType) :
|
Piece::Piece(Polyomino&& polyomino, Block blockType) :
|
||||||
polyomino(polyomino),
|
polyomino(polyomino),
|
||||||
blockType(blockType) {
|
blockType(blockType),
|
||||||
|
rotationState(NONE) {
|
||||||
this->rotationState = NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::rotate(Rotation rotation) {
|
void Piece::rotate(Rotation rotation) {
|
||||||
@@ -38,8 +37,8 @@ void Piece::defaultRotation() {
|
|||||||
this->rotationState = NONE;
|
this->rotationState = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<Position>& Piece::getPositions() const {
|
const Polyomino& Piece::getPositions() const {
|
||||||
return this->polyomino.getPositions();
|
return this->polyomino;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Piece::getLength() const {
|
int Piece::getLength() const {
|
||||||
@@ -54,3 +53,7 @@ std::ostream& operator<<(std::ostream& os, const Piece& piece) {
|
|||||||
os << getConsoleColorCode(piece.blockType) << piece.polyomino << getResetConsoleColorCode();
|
os << getConsoleColorCode(piece.blockType) << piece.polyomino << getResetConsoleColorCode();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Piece::containsSquare(const Position& position) const {
|
||||||
|
return polyomino.contains(position);
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class Piece {
|
|||||||
/**
|
/**
|
||||||
* Creates a piece with a specified shape and block type
|
* 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
|
* Rotates the piece in the specified direction
|
||||||
@@ -36,7 +36,13 @@ class Piece {
|
|||||||
/**
|
/**
|
||||||
* @return The list of positions of the piece
|
* @return The list of positions of the piece
|
||||||
*/
|
*/
|
||||||
const std::set<Position>& getPositions() const;
|
const Polyomino& 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
|
* @return The length of the piece
|
||||||
|
|||||||
@@ -50,11 +50,18 @@ bool PiecesFiles::savePieces(int polyominoSize, std::vector<Polyomino>& polyomin
|
|||||||
std::uint8_t infoByte = (isConvex << 7) + (hasHole << 6) + polyomino.getLength();
|
std::uint8_t infoByte = (isConvex << 7) + (hasHole << 6) + polyomino.getLength();
|
||||||
buffer << infoByte;
|
buffer << infoByte;
|
||||||
|
|
||||||
|
const int bitsNeeded = polyomino.getLength() * polyomino.getLength();
|
||||||
|
const int bytesNeeded = bitsNeeded / 8 + 1;
|
||||||
|
|
||||||
|
static const Polyomino::PolyominoData byteMask = 0xFF;
|
||||||
|
const Polyomino::PolyominoData& polyominoData = polyomino.getPositionsData();
|
||||||
|
|
||||||
// write the positions of the piece
|
// write the positions of the piece
|
||||||
std::uint8_t positionByte;
|
for (int i = 0; i < bytesNeeded; i++) {
|
||||||
for (const Position position : polyomino.getPositions()) {
|
Polyomino::PolyominoData pData = polyominoData >> (i * 8);
|
||||||
positionByte = (position.x << 4) + position.y;
|
unsigned long data =
|
||||||
buffer << positionByte;
|
(pData & byteMask).to_ulong();
|
||||||
|
buffer << static_cast<std::uint8_t>(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,13 +98,12 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
|
|||||||
nextPieceBlockType(pieceBlock);
|
nextPieceBlockType(pieceBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
char convexMask = 0b1000'0000;
|
constexpr char convexMask = 0b1000'0000;
|
||||||
char holeMask = 0b0100'0000;
|
constexpr char holeMask = 0b0100'0000;
|
||||||
char lengthMask = 0b0011'1111;
|
constexpr char lengthMask = 0b0011'1111;
|
||||||
char xMask = 0b1111'0000;
|
|
||||||
char yMask = 0b0000'1111;
|
|
||||||
|
|
||||||
std::uint8_t infoByte;
|
std::uint8_t infoByte;
|
||||||
|
std::uint8_t positionByte;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (!buffer.IsFinished()) {
|
while (!buffer.IsFinished()) {
|
||||||
// if (piecesFile.eof()) break;
|
// if (piecesFile.eof()) break;
|
||||||
@@ -108,21 +114,22 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
|
|||||||
bool hasHole = (infoByte & holeMask) >> 6;
|
bool hasHole = (infoByte & holeMask) >> 6;
|
||||||
int length = (infoByte & lengthMask);
|
int length = (infoByte & lengthMask);
|
||||||
|
|
||||||
|
const int bitsNeeded = length * length;
|
||||||
|
const int bytesNeeded = bitsNeeded / 8 + 1;
|
||||||
|
|
||||||
// read positions
|
// read positions
|
||||||
std::set<Position> piecePositions;
|
Polyomino::PolyominoData polyominoData{};
|
||||||
std::uint8_t positionByte;
|
|
||||||
for (int i = 0; i < polyominoSize; i++) {
|
for (int j = 0; j < bytesNeeded; j++) {
|
||||||
buffer >> positionByte;
|
buffer >> positionByte;
|
||||||
int x = ((unsigned char) positionByte & xMask) >> 4;
|
Polyomino::PolyominoData tempByte(positionByte);
|
||||||
int y = positionByte & yMask;
|
polyominoData |= (tempByte << (j * 8));
|
||||||
piecePositions.insert(Position{x, y});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create piece
|
pieces.emplace_back(Polyomino(std::move(polyominoData), length), pieceBlock);
|
||||||
Piece readPiece(Polyomino(piecePositions, length), pieceBlock);
|
|
||||||
nextPieceBlockType(pieceBlock);
|
nextPieceBlockType(pieceBlock);
|
||||||
|
|
||||||
pieces.push_back(readPiece);
|
|
||||||
if (isConvex) {
|
if (isConvex) {
|
||||||
convexPieces.push_back(i);
|
convexPieces.push_back(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
Polyomino::Polyomino(std::set<Position>&& positions) : positions(0) {
|
||||||
Polyomino::Polyomino(const std::set<Position>& positions) {
|
|
||||||
int minX = INT_MAX;
|
int minX = INT_MAX;
|
||||||
int maxX = INT_MIN;
|
int maxX = INT_MIN;
|
||||||
int minY = INT_MAX;
|
int minY = INT_MAX;
|
||||||
@@ -25,71 +25,64 @@ Polyomino::Polyomino(const std::set<Position>& positions) {
|
|||||||
this->length = std::max(maxX - minX + 1, maxY - minY + 1);
|
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
|
// we normalize here instead of calling this->normalize() to reduce the number of calculations for the generation algorithm
|
||||||
std::set<Position> newPositions;
|
Polyomino newPolyomino({}, this->length);
|
||||||
for (Position position : positions) {
|
for (Position position : positions) {
|
||||||
newPositions.insert(Position{position.x - minX, position.y - minY});
|
newPolyomino.insert(Position(position.x - minX, position.y - minY));
|
||||||
}
|
}
|
||||||
this->positions = std::move(newPositions);
|
this->positions = std::move(newPolyomino.positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Polyomino::Polyomino(const std::set<Position>& positions, int length) :
|
Polyomino::Polyomino(PolyominoData&& positions, std::int8_t length) :
|
||||||
positions(positions),
|
positions(std::move(positions)),
|
||||||
length(length) {
|
length(length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polyomino::normalize() {
|
void Polyomino::normalize() {
|
||||||
int minX = INT_MAX;
|
int minX = INT_MAX;
|
||||||
int minY = INT_MAX;
|
int minY = INT_MAX;
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
if (position.x < minX) minX = position.x;
|
if (position.x < minX) minX = position.x;
|
||||||
if (position.y < minY) minY = position.y;
|
if (position.y < minY) minY = position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<Position> newPositions;
|
Polyomino newPolyomino({}, this->length);
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
newPositions.insert(Position{position.x - minX, position.y - minY});
|
newPolyomino.insert(Position(position.x - minX, position.y - minY));
|
||||||
}
|
}
|
||||||
this->positions = std::move(newPositions);
|
this->positions = std::move(newPolyomino.positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polyomino::rotateCW() {
|
void Polyomino::rotateCW() {
|
||||||
std::set<Position> newPositions;
|
Polyomino temp({}, this->length);
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
newPositions.insert(Position{position.y, (length - 1) - (position.x)});
|
temp.insert(Position(position.y, (length - 1) - (position.x)));
|
||||||
}
|
}
|
||||||
this->positions = std::move(newPositions);
|
this->positions = std::move(temp.positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polyomino::rotate180() {
|
void Polyomino::rotate180() {
|
||||||
std::set<Position> newPositions;
|
Polyomino temp({}, this->length);
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
newPositions.insert(Position{(length - 1) - (position.x), (length - 1) - (position.y)});
|
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() {
|
void Polyomino::rotateCCW() {
|
||||||
std::set<Position> newPositions;
|
Polyomino temp({}, this->length);
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
newPositions.insert(Position{(length - 1) - (position.y), position.x});
|
temp.insert(Position((length - 1) - (position.y), position.x));
|
||||||
}
|
}
|
||||||
this->positions = std::move(newPositions);
|
this->positions = std::move(temp.positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polyomino::goToSpawnPosition() {
|
void Polyomino::goToSpawnPosition() {
|
||||||
// initialize array
|
// initialize array
|
||||||
std::vector<std::vector<int>> linesCompleteness;
|
std::vector<int> empty(this->length, 0);
|
||||||
linesCompleteness.reserve(4);
|
std::vector<std::vector<int>> linesCompleteness(4, empty);
|
||||||
std::vector<int> empty;
|
|
||||||
for (int j = 0; j < this->length; j++) {
|
|
||||||
empty.push_back(0);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
linesCompleteness.push_back(empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculates amount of squares per rows and columns
|
// calculates amount of squares per rows and columns
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
linesCompleteness.at(0).at(position.y) += 1; // 0 = bottom to top = no rotation
|
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(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
|
linesCompleteness.at(2).at((length - 1) - position.y) += 1; // 2 = top to bottom = 180
|
||||||
@@ -156,19 +149,20 @@ void Polyomino::goToSpawnPosition() {
|
|||||||
std::swap(verticalEmptyLines, horizontalEmptyLines);
|
std::swap(verticalEmptyLines, horizontalEmptyLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int minX = INT_MAX;
|
int minX = INT_MAX;
|
||||||
int minY = INT_MAX;
|
int minY = INT_MAX;
|
||||||
for (const Position position : this->positions) {
|
for (const Position position : *this) {
|
||||||
if (position.x < minX) minX = position.x;
|
if (position.x < minX) minX = position.x;
|
||||||
if (position.y < minY) minY = position.y;
|
if (position.y < minY) minY = position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// center the piece with an up bias
|
// center the piece with an up bias
|
||||||
std::set<Position> newPositions;
|
Polyomino temp({}, this->length);
|
||||||
for (const Position position : positions) {
|
for (const Position position : *this) {
|
||||||
newPositions.insert(Position{(position.x - minX) + (verticalEmptyLines / 2), (position.y - minY) + ((horizontalEmptyLines + 1) / 2)});
|
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 {
|
void Polyomino::checkForFlattestSide(const std::vector<std::vector<int>>& linesCompleteness, bool currentFlattestSides[4], int& sideToBeOn, bool checkLeftSide) const {
|
||||||
@@ -216,7 +210,7 @@ bool Polyomino::isConvex() const {
|
|||||||
bool startedColumn = false;
|
bool startedColumn = false;
|
||||||
bool completedColumn = false;
|
bool completedColumn = false;
|
||||||
for (int i = 0; i < this->length; i++) {
|
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;
|
if (completedLine) return false;
|
||||||
else startedLine = true;
|
else startedLine = true;
|
||||||
}
|
}
|
||||||
@@ -224,7 +218,7 @@ bool Polyomino::isConvex() const {
|
|||||||
if (startedLine) completedLine = true;
|
if (startedLine) completedLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->positions.contains(Position{j, i})) {
|
if (this->contains(Position(j, i))) {
|
||||||
if (completedColumn) return false;
|
if (completedColumn) return false;
|
||||||
else startedColumn = true;
|
else startedColumn = true;
|
||||||
}
|
}
|
||||||
@@ -238,31 +232,31 @@ bool Polyomino::isConvex() const {
|
|||||||
|
|
||||||
bool Polyomino::hasHole() const {
|
bool Polyomino::hasHole() const {
|
||||||
// add every empty square on the outer of the box containing the polyomino
|
// add every empty square on the outer of the box containing the polyomino
|
||||||
std::set<Position> emptyPositions;
|
Polyomino temp({}, this->length);
|
||||||
for (int i = 0; i < this->length - 1; i++) {
|
for (int i = 0; i < this->length - 1; i++) {
|
||||||
this->tryToInsertPosition(emptyPositions, Position{i, 0}); // up row
|
this->tryToInsertPosition(temp, Position(i, 0)); // up row
|
||||||
this->tryToInsertPosition(emptyPositions, Position{this->length - 1, i}); // rigth column
|
this->tryToInsertPosition(temp, Position(this->length - 1, i)); // rigth column
|
||||||
this->tryToInsertPosition(emptyPositions, Position{this->length - 1 - i, this->length - 1}); // bottom row
|
this->tryToInsertPosition(temp, Position(this->length - 1 - i, this->length - 1)); // bottom row
|
||||||
this->tryToInsertPosition(emptyPositions, Position{0, this->length - 1 - i}); // left column
|
this->tryToInsertPosition(temp, Position(0, this->length - 1 - i)); // left column
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we didn't reached all empty squares in the box then there was some contained within the polyomino, i.e. there was a hole
|
// if we didn't reached all empty squares in the box then there was some contained within the polyomino, i.e. there was a hole
|
||||||
return (emptyPositions.size() < (this->length * this->length) - this->positions.size());
|
return (temp.getSize() < (this->length * this->length) - this->positions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polyomino::tryToInsertPosition(std::set<Position>& emptyPositions, const Position& candidate) const {
|
void Polyomino::tryToInsertPosition(Polyomino& emptyPositions, const Position& candidate) const {
|
||||||
if (candidate.x >= this->length || candidate.x < 0 || candidate.y >= this->length || candidate.y < 0) return;
|
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
|
// if it's a new empty square, try its neighbors
|
||||||
emptyPositions.insert(candidate);
|
emptyPositions.insert(candidate);
|
||||||
tryToInsertPosition(emptyPositions, Position{candidate.x, candidate.y + 1});
|
tryToInsertPosition(emptyPositions, Position(candidate.x, candidate.y + 1));
|
||||||
tryToInsertPosition(emptyPositions, Position{candidate.x + 1, candidate.y});
|
tryToInsertPosition(emptyPositions, Position(candidate.x + 1, candidate.y));
|
||||||
tryToInsertPosition(emptyPositions, Position{candidate.x, candidate.y - 1});
|
tryToInsertPosition(emptyPositions, Position(candidate.x, candidate.y - 1));
|
||||||
tryToInsertPosition(emptyPositions, Position{candidate.x - 1, candidate.y});
|
tryToInsertPosition(emptyPositions, Position(candidate.x - 1, candidate.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<Position>& Polyomino::getPositions() const {
|
const Polyomino::PolyominoData& Polyomino::getPositionsData() const {
|
||||||
return this->positions;
|
return this->positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,13 +271,19 @@ int Polyomino::getPolyominoSize() const {
|
|||||||
bool Polyomino::operator<(const Polyomino& other) const {
|
bool Polyomino::operator<(const Polyomino& other) const {
|
||||||
if (this->length != other.length) return this->length < other.length;
|
if (this->length != other.length) return this->length < other.length;
|
||||||
|
|
||||||
for (int y = this->length - 1; y >= 0; y--) {
|
assert(other.positions.any() && "The other polyomino is empty !");
|
||||||
for (int x = 0; x < this->length; x++) {
|
|
||||||
bool hasThisPosition = this->positions.contains(Position{x, y});
|
static const PolyominoData longMask = 0xFFFFFFFFFFFFFFFF;
|
||||||
bool hasOtherPosition = other.positions.contains(Position{x, y});
|
const int longsNeeded = this->length * this->length / 64 + 1;
|
||||||
if (hasThisPosition != hasOtherPosition) return hasThisPosition;
|
|
||||||
|
for (int i = 0; i < longsNeeded; i++) {
|
||||||
|
unsigned long l1 = (this->positions >> (i * sizeof(std::uint64_t)) & longMask).to_ulong();
|
||||||
|
unsigned long l2 = (other.positions >> (i * sizeof(std::uint64_t)) & longMask).to_ulong();
|
||||||
|
if (l1 != l2) {
|
||||||
|
return l1 < l2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ bool Polyomino::operator==(const Polyomino& other) const {
|
|||||||
std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino) {
|
std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino) {
|
||||||
for (int y = polyomino.length - 1; y >= 0; y--) {
|
for (int y = polyomino.length - 1; y >= 0; y--) {
|
||||||
for (int x = 0; x < polyomino.length; x++) {
|
for (int x = 0; x < polyomino.length; x++) {
|
||||||
if (polyomino.positions.contains(Position{x, y})) {
|
if (polyomino.contains(Position(x, y))) {
|
||||||
os << "*";
|
os << "*";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -305,3 +305,31 @@ std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino) {
|
|||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Polyomino::getSize() const {
|
||||||
|
return positions.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Polyomino::contains(const Position& position) const {
|
||||||
|
return this->positions[getBitIndex(position)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyomino::insert(const Position& position) {
|
||||||
|
this->positions.set(getBitIndex(position), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyomino::erase(const Position& position) {
|
||||||
|
this->positions.set(getBitIndex(position), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Polyomino::getBitIndex(const Position& position) const {
|
||||||
|
return position.y * this->length + position.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Polyomino::ConstIterator Polyomino::begin() const {
|
||||||
|
return ConstIterator(*this, positions._Find_first());
|
||||||
|
}
|
||||||
|
|
||||||
|
Polyomino::ConstIterator Polyomino::end() const {
|
||||||
|
return ConstIterator(*this, positions.size());
|
||||||
|
}
|
||||||
@@ -5,26 +5,68 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <array>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mathematical object consisting of touching squares on a 2D grid
|
* A mathematical object consisting of touching squares on a 2D grid
|
||||||
*/
|
*/
|
||||||
class Polyomino {
|
class Polyomino {
|
||||||
|
public:
|
||||||
|
static const std::size_t MAX_LENGTH = 16;
|
||||||
|
using PolyominoData = std::bitset<MAX_LENGTH * MAX_LENGTH>;
|
||||||
|
|
||||||
|
class ConstIterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = Position;
|
||||||
|
using const_pointer = const Position*; // or also value_type*
|
||||||
|
using const_reference = const Position&; // or also value_type&
|
||||||
|
public:
|
||||||
|
ConstIterator(const Polyomino& polyomino, std::size_t index) : m_Polyomino(polyomino), m_Index(index) {
|
||||||
|
updatePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reference operator*() const { return m_Position; }
|
||||||
|
const_pointer operator->() { return &m_Position; }
|
||||||
|
|
||||||
|
// Prefix increment
|
||||||
|
ConstIterator& operator++() {
|
||||||
|
m_Index = m_Polyomino.getPositionsData()._Find_next(m_Index);
|
||||||
|
updatePosition();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
friend bool operator== (const ConstIterator& a, const ConstIterator& b) { return a.m_Index == b.m_Index; };
|
||||||
|
friend bool operator!= (const ConstIterator& a, const ConstIterator& b) { return a.m_Index != b.m_Index; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<Position> positions; // the squares composing the polyomino, (0,0) is downleft
|
void updatePosition() {
|
||||||
int length; // the size of the smallest square box in which the polyomino can fit on any rotation
|
m_Position = Position(m_Index % m_Polyomino.getLength(), m_Index / m_Polyomino.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Polyomino& m_Polyomino;
|
||||||
|
std::size_t m_Index;
|
||||||
|
Position m_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
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:
|
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a polyomino with the specified positions and length, wheter it is actually a polyonimo of this length is not checked
|
* 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, int length);
|
Polyomino(PolyominoData&& positions, std::int8_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a polyomino with the specified positions and normalizes it, wheter it is actually a polyonimo is not checked
|
||||||
|
*/
|
||||||
|
Polyomino(std::set<Position>&& positions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the polyomino to the lowest unsigned values (lower row on y = 0, and left-most column on x = 0)
|
* Translates the polyomino to the lowest unsigned values (lower row on y = 0, and left-most column on x = 0)
|
||||||
@@ -74,19 +116,29 @@ class Polyomino {
|
|||||||
/**
|
/**
|
||||||
* Auxiliary method of hasHole()
|
* Auxiliary method of hasHole()
|
||||||
*/
|
*/
|
||||||
void tryToInsertPosition(std::set<Position>& emptypositions, const Position& candidate) const;
|
void tryToInsertPosition(Polyomino& emptypositions, const Position& candidate) const;
|
||||||
|
|
||||||
public:
|
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 length of the polyomino
|
* @return The length of the polyomino
|
||||||
*/
|
*/
|
||||||
int getLength() const;
|
int getLength() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int getSize() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
std::size_t getBitIndex(const Position& position) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of squares in the polyomino
|
* @return The number of squares in the polyomino
|
||||||
*/
|
*/
|
||||||
@@ -110,4 +162,23 @@ class Polyomino {
|
|||||||
* @return A reference to the output stream
|
* @return A reference to the output stream
|
||||||
*/
|
*/
|
||||||
friend std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino);
|
friend std::ostream& operator<<(std::ostream& os, const Polyomino& polyomino);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if it contains the position
|
||||||
|
*/
|
||||||
|
bool contains(const Position& position) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Insert a square at the position
|
||||||
|
*/
|
||||||
|
void insert(const Position& position);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a square at the position
|
||||||
|
*/
|
||||||
|
void erase(const Position& position);
|
||||||
|
|
||||||
|
ConstIterator begin() const;
|
||||||
|
|
||||||
|
ConstIterator end() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A position on a 2D grid
|
* A position on a 2D grid
|
||||||
*/
|
*/
|
||||||
struct Position {
|
struct Position {
|
||||||
int x; // x position
|
std::int8_t x; // x position
|
||||||
int y; // y position
|
std::int8_t y; // y position
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ struct Position {
|
|||||||
* @return The sums of the coordinates of both positions
|
* @return The sums of the coordinates of both positions
|
||||||
*/
|
*/
|
||||||
inline Position operator+(const Position& left, const Position& right) {
|
inline Position operator+(const Position& left, const Position& right) {
|
||||||
return Position{left.x + right.x, left.y + right.y};
|
return Position(left.x + right.x, left.y + right.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +34,7 @@ inline Position& operator+=(Position& left, const Position& right) {
|
|||||||
* @return The difference of the coordinate between the left and right position
|
* @return The difference of the coordinate between the left and right position
|
||||||
*/
|
*/
|
||||||
inline Position operator-(const Position& left, const Position& right) {
|
inline Position operator-(const Position& left, const Position& right) {
|
||||||
return Position{left.x - right.x, left.y - right.y};
|
return Position(left.x - right.x, left.y - right.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -250,9 +250,9 @@ void TextApp::printGame(const Game& game) const {
|
|||||||
for (int y = maxHeight; y >= 0; y--) {
|
for (int y = maxHeight; y >= 0; y--) {
|
||||||
for (int x = 0; x < game.getBoard().getWidth(); x++) {
|
for (int x = 0; x < game.getBoard().getWidth(); x++) {
|
||||||
/* BOARD PRINTING */
|
/* BOARD PRINTING */
|
||||||
bool isActivePieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position{x, y} - game.getActivePiecePosition()));
|
bool isActivePieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position(x, y) - game.getActivePiecePosition()));
|
||||||
bool isGhostPieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position{x, y} - game.getGhostPiecePosition()));
|
bool isGhostPieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position(x, y) - game.getGhostPiecePosition()));
|
||||||
Block block = (isActivePieceHere || isGhostPieceHere) ? game.getActivePiece()->getBlockType() : game.getBoard().getBlock(Position{x, y});
|
Block block = (isActivePieceHere || isGhostPieceHere) ? game.getActivePiece()->getBlockType() : game.getBoard().getBlock(Position(x, y));
|
||||||
|
|
||||||
if (isActivePieceHere || isGhostPieceHere) {
|
if (isActivePieceHere || isGhostPieceHere) {
|
||||||
std::cout << getConsoleColorCode(block);
|
std::cout << getConsoleColorCode(block);
|
||||||
@@ -294,7 +294,7 @@ void TextApp::printGame(const Game& game) const {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < game.getHeldPiece()->getLength(); i++) {
|
for (int i = 0; i < game.getHeldPiece()->getLength(); i++) {
|
||||||
if (game.getHeldPiece()->getPositions().contains(Position{i, printedPieceLineHeight})) {
|
if (game.getHeldPiece()->getPositions().contains(Position(i, printedPieceLineHeight))) {
|
||||||
std::cout << getConsoleColorCode(game.getHeldPiece()->getBlockType()) << "*";
|
std::cout << getConsoleColorCode(game.getHeldPiece()->getBlockType()) << "*";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -316,7 +316,7 @@ void TextApp::printGame(const Game& game) const {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < game.getNextPieces().at(nextQueuePrintedPiece).getLength(); i++) {
|
for (int i = 0; i < game.getNextPieces().at(nextQueuePrintedPiece).getLength(); i++) {
|
||||||
if (game.getNextPieces().at(nextQueuePrintedPiece).getPositions().contains(Position{i, printedPieceLineHeight})) {
|
if (game.getNextPieces().at(nextQueuePrintedPiece).getPositions().contains(Position(i, printedPieceLineHeight))) {
|
||||||
std::cout << getConsoleColorCode(game.getNextPieces().at(nextQueuePrintedPiece).getBlockType()) << "*";
|
std::cout << getConsoleColorCode(game.getNextPieces().at(nextQueuePrintedPiece).getBlockType()) << "*";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -10,30 +10,6 @@ static const unsigned char data_fonts_pressstart_prstartk_ttf[] = {
|
|||||||
#include <data/fonts/pressstart/prstartk.ttf.h>
|
#include <data/fonts/pressstart/prstartk.ttf.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Rotate180_png[] = {
|
|
||||||
#include <data/images/keybinds/Rotate180.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Rotate0_png[] = {
|
|
||||||
#include <data/images/keybinds/Rotate0.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_RotateCCW_png[] = {
|
|
||||||
#include <data/images/keybinds/RotateCCW.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Retry_png[] = {
|
|
||||||
#include <data/images/keybinds/Retry.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_RotateCW_png[] = {
|
|
||||||
#include <data/images/keybinds/RotateCW.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Moveright_png[] = {
|
|
||||||
#include <data/images/keybinds/Moveright.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Harddrop_png[] = {
|
static const unsigned char data_images_keybinds_Harddrop_png[] = {
|
||||||
#include <data/images/keybinds/Harddrop.png.h>
|
#include <data/images/keybinds/Harddrop.png.h>
|
||||||
};
|
};
|
||||||
@@ -42,14 +18,38 @@ static const unsigned char data_images_keybinds_Moveleft_png[] = {
|
|||||||
#include <data/images/keybinds/Moveleft.png.h>
|
#include <data/images/keybinds/Moveleft.png.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Hold_png[] = {
|
static const unsigned char data_images_keybinds_RotateCW_png[] = {
|
||||||
#include <data/images/keybinds/Hold.png.h>
|
#include <data/images/keybinds/RotateCW.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_RotateCCW_png[] = {
|
||||||
|
#include <data/images/keybinds/RotateCCW.png.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Softdrop_png[] = {
|
static const unsigned char data_images_keybinds_Softdrop_png[] = {
|
||||||
#include <data/images/keybinds/Softdrop.png.h>
|
#include <data/images/keybinds/Softdrop.png.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_Moveright_png[] = {
|
||||||
|
#include <data/images/keybinds/Moveright.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_Rotate180_png[] = {
|
||||||
|
#include <data/images/keybinds/Rotate180.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_Hold_png[] = {
|
||||||
|
#include <data/images/keybinds/Hold.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_Rotate0_png[] = {
|
||||||
|
#include <data/images/keybinds/Rotate0.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char data_images_keybinds_Retry_png[] = {
|
||||||
|
#include <data/images/keybinds/Retry.png.h>
|
||||||
|
};
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Pause_png[] = {
|
static const unsigned char data_images_keybinds_Pause_png[] = {
|
||||||
#include <data/images/keybinds/Pause.png.h>
|
#include <data/images/keybinds/Pause.png.h>
|
||||||
};
|
};
|
||||||
@@ -57,16 +57,16 @@ static const unsigned char data_images_keybinds_Pause_png[] = {
|
|||||||
static const Asset assets[] = {
|
static const Asset assets[] = {
|
||||||
{data_fonts_pressstart_prstart_ttf, sizeof(data_fonts_pressstart_prstart_ttf)},
|
{data_fonts_pressstart_prstart_ttf, sizeof(data_fonts_pressstart_prstart_ttf)},
|
||||||
{data_fonts_pressstart_prstartk_ttf, sizeof(data_fonts_pressstart_prstartk_ttf)},
|
{data_fonts_pressstart_prstartk_ttf, sizeof(data_fonts_pressstart_prstartk_ttf)},
|
||||||
{data_images_keybinds_Rotate180_png, sizeof(data_images_keybinds_Rotate180_png)},
|
|
||||||
{data_images_keybinds_Rotate0_png, sizeof(data_images_keybinds_Rotate0_png)},
|
|
||||||
{data_images_keybinds_RotateCCW_png, sizeof(data_images_keybinds_RotateCCW_png)},
|
|
||||||
{data_images_keybinds_Retry_png, sizeof(data_images_keybinds_Retry_png)},
|
|
||||||
{data_images_keybinds_RotateCW_png, sizeof(data_images_keybinds_RotateCW_png)},
|
|
||||||
{data_images_keybinds_Moveright_png, sizeof(data_images_keybinds_Moveright_png)},
|
|
||||||
{data_images_keybinds_Harddrop_png, sizeof(data_images_keybinds_Harddrop_png)},
|
{data_images_keybinds_Harddrop_png, sizeof(data_images_keybinds_Harddrop_png)},
|
||||||
{data_images_keybinds_Moveleft_png, sizeof(data_images_keybinds_Moveleft_png)},
|
{data_images_keybinds_Moveleft_png, sizeof(data_images_keybinds_Moveleft_png)},
|
||||||
{data_images_keybinds_Hold_png, sizeof(data_images_keybinds_Hold_png)},
|
{data_images_keybinds_RotateCW_png, sizeof(data_images_keybinds_RotateCW_png)},
|
||||||
|
{data_images_keybinds_RotateCCW_png, sizeof(data_images_keybinds_RotateCCW_png)},
|
||||||
{data_images_keybinds_Softdrop_png, sizeof(data_images_keybinds_Softdrop_png)},
|
{data_images_keybinds_Softdrop_png, sizeof(data_images_keybinds_Softdrop_png)},
|
||||||
|
{data_images_keybinds_Moveright_png, sizeof(data_images_keybinds_Moveright_png)},
|
||||||
|
{data_images_keybinds_Rotate180_png, sizeof(data_images_keybinds_Rotate180_png)},
|
||||||
|
{data_images_keybinds_Hold_png, sizeof(data_images_keybinds_Hold_png)},
|
||||||
|
{data_images_keybinds_Rotate0_png, sizeof(data_images_keybinds_Rotate0_png)},
|
||||||
|
{data_images_keybinds_Retry_png, sizeof(data_images_keybinds_Retry_png)},
|
||||||
{data_images_keybinds_Pause_png, sizeof(data_images_keybinds_Pause_png)},
|
{data_images_keybinds_Pause_png, sizeof(data_images_keybinds_Pause_png)},
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -74,16 +74,16 @@ static const Asset assets[] = {
|
|||||||
static const std::map<std::string, AssetName> assetMap = {
|
static const std::map<std::string, AssetName> assetMap = {
|
||||||
{"data/fonts/pressstart/prstart.ttf", AssetName::data_fonts_pressstart_prstart_ttf},
|
{"data/fonts/pressstart/prstart.ttf", AssetName::data_fonts_pressstart_prstart_ttf},
|
||||||
{"data/fonts/pressstart/prstartk.ttf", AssetName::data_fonts_pressstart_prstartk_ttf},
|
{"data/fonts/pressstart/prstartk.ttf", AssetName::data_fonts_pressstart_prstartk_ttf},
|
||||||
{"data/images/keybinds/Rotate180.png", AssetName::data_images_keybinds_Rotate180_png},
|
|
||||||
{"data/images/keybinds/Rotate0.png", AssetName::data_images_keybinds_Rotate0_png},
|
|
||||||
{"data/images/keybinds/RotateCCW.png", AssetName::data_images_keybinds_RotateCCW_png},
|
|
||||||
{"data/images/keybinds/Retry.png", AssetName::data_images_keybinds_Retry_png},
|
|
||||||
{"data/images/keybinds/RotateCW.png", AssetName::data_images_keybinds_RotateCW_png},
|
|
||||||
{"data/images/keybinds/Moveright.png", AssetName::data_images_keybinds_Moveright_png},
|
|
||||||
{"data/images/keybinds/Harddrop.png", AssetName::data_images_keybinds_Harddrop_png},
|
{"data/images/keybinds/Harddrop.png", AssetName::data_images_keybinds_Harddrop_png},
|
||||||
{"data/images/keybinds/Moveleft.png", AssetName::data_images_keybinds_Moveleft_png},
|
{"data/images/keybinds/Moveleft.png", AssetName::data_images_keybinds_Moveleft_png},
|
||||||
{"data/images/keybinds/Hold.png", AssetName::data_images_keybinds_Hold_png},
|
{"data/images/keybinds/RotateCW.png", AssetName::data_images_keybinds_RotateCW_png},
|
||||||
|
{"data/images/keybinds/RotateCCW.png", AssetName::data_images_keybinds_RotateCCW_png},
|
||||||
{"data/images/keybinds/Softdrop.png", AssetName::data_images_keybinds_Softdrop_png},
|
{"data/images/keybinds/Softdrop.png", AssetName::data_images_keybinds_Softdrop_png},
|
||||||
|
{"data/images/keybinds/Moveright.png", AssetName::data_images_keybinds_Moveright_png},
|
||||||
|
{"data/images/keybinds/Rotate180.png", AssetName::data_images_keybinds_Rotate180_png},
|
||||||
|
{"data/images/keybinds/Hold.png", AssetName::data_images_keybinds_Hold_png},
|
||||||
|
{"data/images/keybinds/Rotate0.png", AssetName::data_images_keybinds_Rotate0_png},
|
||||||
|
{"data/images/keybinds/Retry.png", AssetName::data_images_keybinds_Retry_png},
|
||||||
{"data/images/keybinds/Pause.png", AssetName::data_images_keybinds_Pause_png},
|
{"data/images/keybinds/Pause.png", AssetName::data_images_keybinds_Pause_png},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ struct Asset {
|
|||||||
enum class AssetName {
|
enum class AssetName {
|
||||||
data_fonts_pressstart_prstart_ttf,
|
data_fonts_pressstart_prstart_ttf,
|
||||||
data_fonts_pressstart_prstartk_ttf,
|
data_fonts_pressstart_prstartk_ttf,
|
||||||
data_images_keybinds_Rotate180_png,
|
|
||||||
data_images_keybinds_Rotate0_png,
|
|
||||||
data_images_keybinds_RotateCCW_png,
|
|
||||||
data_images_keybinds_Retry_png,
|
|
||||||
data_images_keybinds_RotateCW_png,
|
|
||||||
data_images_keybinds_Moveright_png,
|
|
||||||
data_images_keybinds_Harddrop_png,
|
data_images_keybinds_Harddrop_png,
|
||||||
data_images_keybinds_Moveleft_png,
|
data_images_keybinds_Moveleft_png,
|
||||||
data_images_keybinds_Hold_png,
|
data_images_keybinds_RotateCW_png,
|
||||||
|
data_images_keybinds_RotateCCW_png,
|
||||||
data_images_keybinds_Softdrop_png,
|
data_images_keybinds_Softdrop_png,
|
||||||
|
data_images_keybinds_Moveright_png,
|
||||||
|
data_images_keybinds_Rotate180_png,
|
||||||
|
data_images_keybinds_Hold_png,
|
||||||
|
data_images_keybinds_Rotate0_png,
|
||||||
|
data_images_keybinds_Retry_png,
|
||||||
data_images_keybinds_Pause_png,
|
data_images_keybinds_Pause_png,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user