mis en place la PR de simon sur les couleurs
This commit is contained in:
@@ -5,13 +5,16 @@
|
||||
#include "Bag.h"
|
||||
#include "LineClear.h"
|
||||
|
||||
#include <Vector>
|
||||
#include <Set>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
|
||||
GameBoard::GameBoard(int boardWidth, int boardHeight, const std::vector<Piece>& bag, int nextQueueLength) : board(boardWidth, boardHeight), generator(bag), nextQueueLength(nextQueueLength) {
|
||||
// initialize queue
|
||||
GameBoard::GameBoard(int boardWidth, int boardHeight, const std::vector<Piece>& bag, int nextQueueLength) :
|
||||
board(boardWidth, boardHeight),
|
||||
generator(bag),
|
||||
nextQueueLength(nextQueueLength) {
|
||||
|
||||
this->nextQueue.clear();
|
||||
for (int i = 0; i < nextQueueLength; i++) {
|
||||
this->nextQueue.push_back(this->generator.getNext());
|
||||
@@ -19,8 +22,7 @@ GameBoard::GameBoard(int boardWidth, int boardHeight, const std::vector<Piece>&
|
||||
}
|
||||
|
||||
bool GameBoard::moveLeft() {
|
||||
// check if the piece can be moved one cell left
|
||||
if (this->isActivePieceInWall(Cell{-1, 0})) {
|
||||
if (this->isActivePieceInWall(Position{-1, 0})) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
@@ -31,8 +33,7 @@ bool GameBoard::moveLeft() {
|
||||
}
|
||||
|
||||
bool GameBoard::moveRight() {
|
||||
// check if the piece can be moved one cell right
|
||||
if (this->isActivePieceInWall(Cell{1, 0})) {
|
||||
if (this->isActivePieceInWall(Position{1, 0})) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
@@ -43,8 +44,7 @@ bool GameBoard::moveRight() {
|
||||
}
|
||||
|
||||
bool GameBoard::moveDown() {
|
||||
// check if the piece can be moved one cell down
|
||||
if (this->isActivePieceInWall(Cell{0, -1})) {
|
||||
if (this->isActivePieceInWall(Position{0, -1})) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
@@ -55,36 +55,35 @@ bool GameBoard::moveDown() {
|
||||
}
|
||||
|
||||
bool GameBoard::rotate(Rotation rotation) {
|
||||
// copy the original piece before rotating it
|
||||
Piece stored = *this->activePiece;
|
||||
this->rotate(rotation);
|
||||
|
||||
// check if the piece can rotate
|
||||
// before trying to kick, check if the piece can rotate without kicking
|
||||
if (!this->isActivePieceInWall()) {
|
||||
this->isLastMoveKick = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the list of cells that touches the original piece
|
||||
std::set<Cell> safeCells;
|
||||
for (Cell cell : stored.getPositions()) {
|
||||
Cell cellInGrid(cell + this->activePiecePosition);
|
||||
safeCells.insert(cellInGrid);
|
||||
safeCells.insert(cellInGrid + Cell{0, 1});
|
||||
safeCells.insert(cellInGrid + Cell{1, 0});
|
||||
safeCells.insert(cellInGrid + Cell{0, -1});
|
||||
safeCells.insert(cellInGrid + Cell{-1, 0});
|
||||
// get the list of positions that touches the original piece
|
||||
std::set<Position> safePositions;
|
||||
for (Position position : stored.getPositions()) {
|
||||
Position positionInGrid(position + this->activePiecePosition);
|
||||
safePositions.insert(positionInGrid);
|
||||
safePositions.insert(positionInGrid + Position{0, 1});
|
||||
safePositions.insert(positionInGrid + Position{1, 0});
|
||||
safePositions.insert(positionInGrid + Position{0, -1});
|
||||
safePositions.insert(positionInGrid + Position{-1, 0});
|
||||
}
|
||||
|
||||
// try kicking the piece down
|
||||
bool suceeded = this->tryKicking(true, safeCells);
|
||||
bool suceeded = this->tryKicking(true, safePositions);
|
||||
if (suceeded) {
|
||||
this->isLastMoveKick = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if it doesn't work try kicking the piece up
|
||||
suceeded = this->tryKicking(false, safeCells);
|
||||
suceeded = this->tryKicking(false, safePositions);
|
||||
if (suceeded) {
|
||||
this->isLastMoveKick = true;
|
||||
return true;
|
||||
@@ -95,8 +94,8 @@ bool GameBoard::rotate(Rotation rotation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::tryKicking(bool testingBottom, const std::set<Cell>& safeCells) {
|
||||
// we try from the original height of the piece, moving vertically as long as the kicked piece touches the original
|
||||
bool GameBoard::tryKicking(bool testingBottom, const std::set<Position>& safePositions) {
|
||||
// we try from the original height of the piece, moving vertically as long as the kicked piece touches the original at least once on this row
|
||||
bool overlapsVertically = true;
|
||||
int j = 0;
|
||||
do {
|
||||
@@ -107,13 +106,11 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Cell>& safeCells)
|
||||
do {
|
||||
// check right before right arbitrarly, we don't decide this with rotations since it would still be arbitrary with 180° rotations
|
||||
if (overlapsRight) {
|
||||
Cell shift{+i, j};
|
||||
// the kicked position must touch the original piece
|
||||
if (!this->activePieceOverlapsOneCell(safeCells, shift)) {
|
||||
Position shift{+i, j};
|
||||
if (!this->activePieceOverlapsOnePosition(safePositions, shift)) {
|
||||
overlapsLeft = false;
|
||||
}
|
||||
else {
|
||||
// if the position is valid we place the active piece there
|
||||
if (!this->isActivePieceInWall(shift)) {
|
||||
this->activePiecePosition += shift;
|
||||
return true;
|
||||
@@ -123,8 +120,8 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Cell>& safeCells)
|
||||
|
||||
// do the same on the left side
|
||||
if (overlapsLeft) {
|
||||
Cell shift{-i, j};
|
||||
if (!this->activePieceOverlapsOneCell(safeCells, shift)) {
|
||||
Position shift{-i, j};
|
||||
if (!this->activePieceOverlapsOnePosition(safePositions, shift)) {
|
||||
overlapsLeft = false;
|
||||
}
|
||||
else {
|
||||
@@ -138,12 +135,10 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Cell>& safeCells)
|
||||
i++;
|
||||
} while (overlapsLeft && overlapsRight);
|
||||
|
||||
// test if no position touched the original piece
|
||||
if (i == 1) {
|
||||
overlapsVertically = false;
|
||||
}
|
||||
|
||||
// move one line up or down
|
||||
(testingBottom) ? j-- : j++;
|
||||
} while (overlapsVertically);
|
||||
|
||||
@@ -151,15 +146,11 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Cell>& safeCells)
|
||||
}
|
||||
|
||||
bool GameBoard::hold(Rotation initialRotation) {
|
||||
// swap with held piece
|
||||
std::swap(this->activePiece, this->heldPiece);
|
||||
|
||||
// if it's the first time holding try the next piece
|
||||
bool isFirstTimeHolding = false;
|
||||
if (this->activePiece == nullptr) {
|
||||
isFirstTimeHolding = true;
|
||||
|
||||
// if no pieces in next queue look at what the next would be
|
||||
bool isFirstTimeHolding = (this->activePiece == nullptr);
|
||||
if (isFirstTimeHolding) {
|
||||
// try with the next piece in queue since there is no piece in the hold box yet
|
||||
if (this->nextQueueLength == 0) {
|
||||
this->activePiece = std::make_shared<Piece>(this->generator.lookNext());
|
||||
}
|
||||
@@ -168,10 +159,8 @@ bool GameBoard::hold(Rotation initialRotation) {
|
||||
}
|
||||
}
|
||||
|
||||
// set the spawned piece to the correct position
|
||||
this->goToSpawnPosition();
|
||||
|
||||
// apply initial rotation
|
||||
Piece stored = *this->activePiece;
|
||||
this->rotate(initialRotation);
|
||||
|
||||
@@ -189,14 +178,10 @@ bool GameBoard::hold(Rotation initialRotation) {
|
||||
}
|
||||
}
|
||||
|
||||
// if it's the first time holding, confirm we keep this piece
|
||||
if (isFirstTimeHolding) {
|
||||
if (this->nextQueueLength == 0) {
|
||||
this->generator.getNext();
|
||||
}
|
||||
else {
|
||||
this->spawnNextPiece();
|
||||
}
|
||||
// confirm we keep the piece we tried with
|
||||
this->nextQueue.push_back(this->generator.getNext());
|
||||
this->nextQueue.erase(this->nextQueue.begin());
|
||||
}
|
||||
|
||||
// this piece has done nothing yet
|
||||
@@ -206,39 +191,34 @@ bool GameBoard::hold(Rotation initialRotation) {
|
||||
}
|
||||
|
||||
bool GameBoard::spawnNextPiece() {
|
||||
// add a piece to the queue
|
||||
// generate a new piece
|
||||
this->nextQueue.push_back(this->generator.getNext());
|
||||
|
||||
// get next piece from queue
|
||||
this->activePiece = std::make_shared<Piece>(this->nextQueue.front());
|
||||
this->nextQueue.erase(this->nextQueue.begin());
|
||||
|
||||
// set the spawned piece to the correct position
|
||||
this->goToSpawnPosition();
|
||||
|
||||
// this piece has done nothing yet
|
||||
this->isLastMoveKick = false;
|
||||
|
||||
// returns wheter the piece can spawn correctly
|
||||
return !this->isActivePieceInWall();
|
||||
}
|
||||
|
||||
bool GameBoard::touchesGround() {
|
||||
return this->isActivePieceInWall(Cell{0, -1});
|
||||
return this->isActivePieceInWall(Position{0, -1});
|
||||
}
|
||||
|
||||
LineClear GameBoard::lockPiece() {
|
||||
// check if the piece is locked in place
|
||||
bool isLocked = (this->isActivePieceInWall(Cell{0, 1}) && this->isActivePieceInWall(Cell{1, 0}) &&
|
||||
this->isActivePieceInWall(Cell{-1, 0}) && this->isActivePieceInWall(Cell{0, -1}));
|
||||
bool isLockedInPlace = (this->isActivePieceInWall(Position{0, 1}) && this->isActivePieceInWall(Position{1, 0})
|
||||
&& this->isActivePieceInWall(Position{-1, 0}) && this->isActivePieceInWall(Position{0, -1}));
|
||||
|
||||
// put the piece in the board
|
||||
for (Cell cell : this->activePiece->getPositions()) {
|
||||
this->board.addBlock(cell + this->activePiecePosition, this->activePiece->getColor());
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
this->board.addBlock(position + this->activePiecePosition, this->activePiece->getBlockType());
|
||||
}
|
||||
|
||||
// check for lines to clear
|
||||
return LineClear{this->board.clearRows(), isLocked, (!isLocked) && this->isLastMoveKick};
|
||||
return LineClear{this->board.clearRows(), isLockedInPlace, (!isLockedInPlace) && this->isLastMoveKick};
|
||||
}
|
||||
|
||||
Board GameBoard::getBoard() const {
|
||||
@@ -249,7 +229,7 @@ Piece GameBoard::getActivePiece() const {
|
||||
return *this->activePiece;
|
||||
}
|
||||
|
||||
Cell GameBoard::getActivePiecePosition() const {
|
||||
Position GameBoard::getActivePiecePosition() const {
|
||||
return this->activePiecePosition;
|
||||
}
|
||||
|
||||
@@ -261,31 +241,28 @@ std::vector<Piece> GameBoard::getNextPieces() const {
|
||||
return this->nextQueue;
|
||||
}
|
||||
|
||||
bool GameBoard::isActivePieceInWall(const Cell& shift) const {
|
||||
// check if every cell of the active piece is in an empty spot
|
||||
for (Cell cell : this->activePiece->getPositions()) {
|
||||
if (this->board.getBlock(cell + this->activePiecePosition + shift) != NOTHING) return true;
|
||||
bool GameBoard::isActivePieceInWall(const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (this->board.getBlock(position + this->activePiecePosition + shift) != NOTHING) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::activePieceOverlapsOneCell(const std::set<Cell>& safeCells, const Cell& shift) const {
|
||||
// check if one cell of the translated active piece overlaps with one cell of the given piece set
|
||||
for (Cell cell : this->activePiece->getPositions()) {
|
||||
if (safeCells.contains(cell + shift)) return true;
|
||||
bool GameBoard::activePieceOverlapsOnePosition(const std::set<Position>& safePositions, const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (safePositions.contains(position + this->activePiecePosition + shift)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameBoard::goToSpawnPosition() {
|
||||
// get the lowest cell of the piece
|
||||
int lowestCell = this->activePiece->getLength() - 1;
|
||||
for (Cell cell : this->activePiece->getPositions()) {
|
||||
if (cell.y < lowestCell) lowestCell = cell.y;
|
||||
int lowestPosition = this->activePiece->getLength() - 1;
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (position.y < lowestPosition) lowestPosition = position.y;
|
||||
}
|
||||
|
||||
// set the piece one line above the board
|
||||
this->activePiecePosition.y = this->board.getBaseHeight() - lowestCell;
|
||||
this->activePiecePosition.y = this->board.getBaseHeight() - lowestPosition;
|
||||
|
||||
// center the piece horizontally, biased towards left
|
||||
this->activePiecePosition.x = (this->board.getWidth() - this->activePiece->getLength()) / 2;
|
||||
@@ -294,15 +271,13 @@ void GameBoard::goToSpawnPosition() {
|
||||
std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
||||
// print over the board (only the active piece if it is there)
|
||||
if (gameboard.activePiece != nullptr) {
|
||||
Block pieceBlockType = gameboard.activePiece->getBlockType();
|
||||
os << getConsoleColorCode(pieceBlockType);
|
||||
|
||||
// change to the color of the active piece
|
||||
Color pieceColor = gameboard.activePiece->getColor();
|
||||
os << COLOR_CODES[pieceColor];
|
||||
|
||||
// print only the cell 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 x = 0; x < gameboard.board.getWidth(); x++) {
|
||||
bool hasActivePiece = gameboard.activePiece->getPositions().contains(Cell{x, y} - gameboard.activePiecePosition);
|
||||
bool hasActivePiece = gameboard.activePiece->getPositions().contains(Position{x, y} - gameboard.activePiecePosition);
|
||||
if (hasActivePiece) {
|
||||
os << "*";
|
||||
}
|
||||
@@ -315,21 +290,19 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
||||
}
|
||||
|
||||
// print the board
|
||||
Color pieceColor = (gameboard.activePiece == nullptr) ? NOTHING : gameboard.activePiece->getColor();
|
||||
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(Cell{x, y} - gameboard.activePiecePosition);
|
||||
bool hasActivePiece = (gameboard.activePiece == nullptr) ? false : gameboard.activePiece->getPositions().contains(Position{x, y} - gameboard.activePiecePosition);
|
||||
|
||||
// if the active piece is on this cell, print it
|
||||
// the active piece takes visual priority over the board
|
||||
if (hasActivePiece) {
|
||||
os << COLOR_CODES[pieceColor];
|
||||
os << getConsoleColorCode(pieceBlockType);
|
||||
os << "*";
|
||||
}
|
||||
|
||||
// else print the cell of the board
|
||||
else {
|
||||
Color block = gameboard.board.getBlock(Cell{x, y});
|
||||
os << COLOR_CODES[block];
|
||||
Block block = gameboard.board.getBlock(Position{x, y});
|
||||
os << getConsoleColorCode(block);
|
||||
if (block != NOTHING) {
|
||||
os << "*";
|
||||
}
|
||||
@@ -341,7 +314,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
// print held piece
|
||||
// print hold box
|
||||
os << "Hold:" << std::endl;
|
||||
if (!(gameboard.heldPiece == nullptr)) {
|
||||
os << *gameboard.heldPiece;
|
||||
@@ -353,8 +326,7 @@ std::ostream& operator<<(std::ostream& os, const GameBoard& gameboard) {
|
||||
os << piece;
|
||||
}
|
||||
|
||||
// reset console color
|
||||
os << COLOR_RESET;
|
||||
os << getResetConsoleColorCode();
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user