check return values (movePiece), offload some logic into Player class
This commit is contained in:
@@ -78,81 +78,113 @@ void Engine::nextTurn() {
|
||||
|
||||
// Wybieranie pionka
|
||||
bool pickAPlace = false;
|
||||
bool isMovePossible = checkPossibleMoves(currentPlayer.getColor(), 6) > 0;
|
||||
// Wylosowanie szóstki to specjalny przypadek
|
||||
if (diceRoll == 6) {
|
||||
|
||||
std::string choice;
|
||||
switch (currentPlayer.pawnsActive) {
|
||||
isMovePossible |= currentPlayer.pawnsAtBase > 0;
|
||||
|
||||
// 0 pionków na planszy - musi wyjść pionkiem
|
||||
case 0:
|
||||
std::cout << currentPlayer.getName() << " wychodzi pierwszym pionkiem z bazy.\n";
|
||||
this->spawnPiece(currentPlayer.getColor(), 0);
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
if (isMovePossible) {
|
||||
|
||||
// 1, 2, 3 pionki na planszy - może wyjść z bazy albo ruszyć pionek
|
||||
case 1: case 2: case 3:
|
||||
std::string choice;
|
||||
bool pawnMoved = false;
|
||||
switch (currentPlayer.pawnsActive) {
|
||||
|
||||
std::cout << "Co chcesz zrobic?\n";
|
||||
std::cout << "a) Wyjsc pionkiem z bazy\n"
|
||||
<< "b) Wykonac ruch wyciagnietym wczesniej pionkiem\n"
|
||||
<< "> ";
|
||||
// 0 pionków na planszy - musi wyjść pionkiem
|
||||
case 0:
|
||||
std::cout << currentPlayer.getName() << " wychodzi pierwszym pionkiem z bazy.\n";
|
||||
this->spawnPiece(currentPlayer.getColor(), 0);
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
|
||||
while (true) {
|
||||
// 1, 2, 3 pionki na planszy - może wyjść z bazy albo ruszyć pionek
|
||||
case 1: case 2: case 3:
|
||||
|
||||
// getline() nie pozostawia nic w buforze wejściowym, dlatego nie musimy
|
||||
// aż tak na niego uważać, jak w przypadku cin'a.
|
||||
std::cout << "Co chcesz zrobic?\n";
|
||||
std::cout << "a) Wyjsc pionkiem z bazy\n"
|
||||
<< "b) Wykonac ruch wyciagnietym wczesniej pionkiem\n"
|
||||
<< "> ";
|
||||
|
||||
choice = this->board.asyncStrGetline();
|
||||
choice[0] |= 32;
|
||||
while (true) {
|
||||
|
||||
if (choice[0] == 'a') {
|
||||
// getline() nie pozostawia nic w buforze wejściowym, dlatego nie musimy
|
||||
// aż tak na niego uważać, jak w przypadku cin'a.
|
||||
|
||||
pickAPlace = false;
|
||||
std::cout << currentPlayer.getName() << " wychodzi "
|
||||
<< currentPlayer.pawnsActive + 1 << ". pionkiem z bazy.\n";
|
||||
// Rusz pierwszy możliwy pionek w bazie:
|
||||
this->spawnPiece(currentPlayer.getColor(), this->getFirstPawnAtBase(currentPlayer.getColor()));
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
choice = this->board.asyncStrGetline();
|
||||
choice[0] |= 32;
|
||||
|
||||
} else if (choice[0] == 'b') {
|
||||
if (choice[0] == 'a') {
|
||||
|
||||
if (currentPlayer.pawnsActive > 1) {
|
||||
pickAPlace = true;
|
||||
} else {
|
||||
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||
<< diceRoll << " pol do przodu.\n";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
short* relativePawns = currentPlayer.getRelativePawns();
|
||||
if (relativePawns[i] >= 0)
|
||||
this->movePiece(currentPlayer.getColor(), relPosToField(currentPlayer.getColor(), relativePawns[i]), diceRoll);
|
||||
}
|
||||
this->pawnmoveBuffer.play();
|
||||
pickAPlace = false;
|
||||
std::cout << currentPlayer.getName() << " wychodzi "
|
||||
<< currentPlayer.pawnsActive + 1 << ". pionkiem z bazy.\n";
|
||||
// Rusz pierwszy możliwy pionek w bazie:
|
||||
this->spawnPiece(currentPlayer.getColor(), this->getFirstPawnAtBase(currentPlayer.getColor()));
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
|
||||
} else if (choice[0] == 'b') {
|
||||
|
||||
if (currentPlayer.pawnsActive > 1) {
|
||||
pickAPlace = true;
|
||||
break;
|
||||
} else {
|
||||
|
||||
// Sprawdź, czy gracz może ruszyć jedyny pionek o tyle pól do przodu
|
||||
for (int i = 0; i < 4; i++) {
|
||||
short* relativePawns = currentPlayer.getRelativePawns();
|
||||
if (relativePawns[i] >= 0) {
|
||||
pawnMoved = this->movePiece(currentPlayer.getColor(), relPosToField(currentPlayer.getColor(), relativePawns[i]), diceRoll);
|
||||
if (pawnMoved) break;
|
||||
}
|
||||
}
|
||||
if (pawnMoved) {
|
||||
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||
<< diceRoll << " pol do przodu.\n";
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
} else {
|
||||
std::cout << "Ups! Nie mozesz tego zrobic!\n";
|
||||
std::cout << "Jedyna opcja to zagranie kolejnym pionkiem.\n";
|
||||
this->invalidBuffer.play();
|
||||
this->board.smartSleep(1000);
|
||||
// Zróbmy to, co w a)
|
||||
pickAPlace = false;
|
||||
std::cout << currentPlayer.getName() << " wychodzi "
|
||||
<< currentPlayer.pawnsActive + 1 << ". pionkiem z bazy.\n";
|
||||
// Rusz pierwszy możliwy pionek w bazie:
|
||||
this->spawnPiece(currentPlayer.getColor(), this->getFirstPawnAtBase(currentPlayer.getColor()));
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
std::cout << "Podaj jedna z wymienionych odpowiedzi!\n> ";
|
||||
this->invalidBuffer.play();
|
||||
this->board.smartSleep(1000);
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
std::cout << "Podaj jedna z wymienionych odpowiedzi!\n> ";
|
||||
this->invalidBuffer.play();
|
||||
this->board.smartSleep(1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
// 4 pionki na planszy - musi ruszyć pionek, o ile może
|
||||
case 4:
|
||||
pickAPlace = true;
|
||||
break;
|
||||
// 4 pionki na planszy - musi ruszyć pionek, o ile może
|
||||
case 4:
|
||||
pickAPlace = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Jeśli nie wypadło 6, gracz musi ruszyć któryś z pionków
|
||||
bool pawnMoved = false;
|
||||
switch (currentPlayer.pawnsActive) {
|
||||
|
||||
// 0 pionków na planszy
|
||||
@@ -167,15 +199,18 @@ void Engine::nextTurn() {
|
||||
// dlatego ruszamy go za niego.
|
||||
pickAPlace = false;
|
||||
// TODO: znajdź ten pionek i ustaw selectedField na niego!!!
|
||||
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||
<< diceRoll << " pol do przodu.\n";
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
short* relativePawns = currentPlayer.getRelativePawns();
|
||||
if (relativePawns[i] >= 0)
|
||||
this->movePiece(currentPlayer.getColor(), relPosToField(currentPlayer.getColor(), relativePawns[i]), diceRoll);
|
||||
pawnMoved = this->movePiece(currentPlayer.getColor(), relPosToField(currentPlayer.getColor(), relativePawns[i]), diceRoll);
|
||||
}
|
||||
if (pawnMoved) {
|
||||
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||
<< diceRoll << " pol do przodu.\n";
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
}
|
||||
this->pawnmoveBuffer.play();
|
||||
this->board.smartSleep(2000);
|
||||
break;
|
||||
|
||||
// 2, 3, 4 pionki na planszy
|
||||
@@ -275,6 +310,22 @@ void Engine::nextTurn() {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts field to player's unique color.
|
||||
*
|
||||
* @param[in] field The field
|
||||
*
|
||||
* @return Player's color.
|
||||
*/
|
||||
short Engine::fieldToColor(short field) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (this->board.fields[field][i] != 0) {
|
||||
return this->board.fields[field][i] - 4;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn a field into the first pawn inside it.
|
||||
*
|
||||
@@ -284,12 +335,38 @@ void Engine::nextTurn() {
|
||||
* @return Player's pawn ID, between 0 and 3.
|
||||
*/
|
||||
short Engine::fieldToFirstPawnId(short color, short field) {
|
||||
// TODO
|
||||
return 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (this->board.fields[field][i] == color + 4) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates through player's pawns to check if they can move.
|
||||
* @brief Check if a pawn can move.
|
||||
*
|
||||
* @param[in] color Player's color
|
||||
* @param[in] pawnId Player's unique pawn ID, ranges from 0-3
|
||||
* @param[in] steps Amount of steps
|
||||
*
|
||||
* @return Returns either true or false, depending if the move is possible or not.
|
||||
*/
|
||||
bool Engine::isMoveLegal(short color, short pawnId, short steps) {
|
||||
// kopia tego, co jest w Engine::movePawn()
|
||||
short field = relPosToField(color, this->players[color].getRelativePawns()[pawnId]);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (field == getPawnInitialPosition(color, i))
|
||||
return false;
|
||||
}
|
||||
if (this->board.fields[field][pawnId] == color + 4) {
|
||||
short relPos = fieldToRelPos(color, field);
|
||||
if (relPos + steps < 44) return true;
|
||||
else return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates through player's pawns on the board to check if they can move.
|
||||
*
|
||||
* @param[in] color Player's color
|
||||
* @param[in] steps Amount of steps
|
||||
@@ -297,8 +374,13 @@ short Engine::fieldToFirstPawnId(short color, short field) {
|
||||
* @return Returns the number of pawns which can be moved given the step count.
|
||||
*/
|
||||
short Engine::checkPossibleMoves(short color, short steps) {
|
||||
// TODO
|
||||
return 0;
|
||||
short possibleMoves = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Nie sprawdzaj pionków, które nie są na planszy
|
||||
if (this->players[this->currentPlayerIndex].getRelativePawns()[i] == -1) continue;
|
||||
if (this->isMoveLegal(color, i, steps)) possibleMoves++;
|
||||
}
|
||||
return possibleMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,6 +427,15 @@ short Engine::getFirstPawnNotAtBase(short color) {
|
||||
*/
|
||||
short Engine::spawnPiece(short color, short pawnId) {
|
||||
short * relativePieces = players[color].getRelativePawns();
|
||||
short spawnField = relPosToField(color, 0);
|
||||
short existingPieceColor = fieldToColor(spawnField);
|
||||
// Zbij pionek, jeśli stoi na nim przeciwnik
|
||||
if (existingPieceColor != color && existingPieceColor != -1) {
|
||||
/*for (int i = 0; i < 4; i++) {
|
||||
if (this->board.fields[spawnField][i] != 0) players[existingPieceColor].sendToBase(i);
|
||||
}*/
|
||||
this->takePawns(existingPieceColor, spawnField);
|
||||
}
|
||||
if (relativePieces[pawnId] == -1) {
|
||||
players[color].sendToBoard(pawnId);
|
||||
this->board.fields[relPosToField(color, relativePieces[pawnId])][pawnId] = color + 4;
|
||||
@@ -381,8 +472,9 @@ short Engine::takePawns(short color, short field) {
|
||||
short color = this->board.fields[field][i] - 4;
|
||||
|
||||
// Zaktualizuj liczbę pionków gracza
|
||||
this->players[color].pawnsActive -= 1;
|
||||
this->players[color].pawnsAtBase += 1;
|
||||
/*this->players[color].pawnsActive -= 1;
|
||||
this->players[color].pawnsAtBase += 1;*/
|
||||
players[color].sendToBase(i);
|
||||
|
||||
// Ustaw pionek na odpowiednie miejsce w bazie
|
||||
this->board.fields[getPawnInitialPosition(color, i)][i] = color + 4;
|
||||
@@ -404,6 +496,13 @@ short Engine::takePawns(short color, short field) {
|
||||
* @return Returns true on success, false on failure.
|
||||
*/
|
||||
bool Engine::movePiece(short color, short field, short steps) { // podajemy color dla sanity-checku, czy użytkownik nie chce ruszyć nie swojego pionka
|
||||
|
||||
// Nie pozwól użytkownikowi wybrać (i w konsekwencji ruszyć) pionków w bazie
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (field == getPawnInitialPosition(color, i))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (this->board.fields[field][i] == color + 4) {
|
||||
// Znaleźliśmy pionek do przesunięcia, teraz pytanie:
|
||||
@@ -423,7 +522,7 @@ bool Engine::movePiece(short color, short field, short steps) { // podajemy colo
|
||||
}
|
||||
}
|
||||
// - jeśli ma, musimy go (/je) zbić
|
||||
if (isNewFieldOccupied) takePawns(occupyingColor, newField);
|
||||
if (isNewFieldOccupied && color != occupyingColor) takePawns(occupyingColor, newField);
|
||||
// - w końcu, dopisujemy pionek bieżącego gracza
|
||||
this->board.fields[newField][i] = color + 4;
|
||||
this->players[this->currentPlayerIndex].unsafeMovePiece(i, steps);
|
||||
|
||||
@@ -53,18 +53,40 @@ void Player::movePawn(int pawnIndex, int steps) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Pawn>& Player::getPawns() {
|
||||
return pawns;
|
||||
}
|
||||
|
||||
bool Player::hasWon() const {
|
||||
return pawnsFinished == pawns.size();
|
||||
short lastPosition = 43;
|
||||
short totalPawnsAtHome = 0;
|
||||
// szuka wartości pomiędzy 40-43
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (this->relativePawns[j] == lastPosition - i) totalPawnsAtHome++;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
std::cout << "(Player.cpp) totalPawnsAtHome: " << totalPawnsAtHome << "\n";
|
||||
#endif
|
||||
return totalPawnsAtHome == 4;
|
||||
}
|
||||
|
||||
short* Player::getRelativePawns() {
|
||||
return this->relativePawns;
|
||||
}
|
||||
|
||||
void Player::recalculatePawnStates() {
|
||||
short temp_atBase = 0;
|
||||
short temp_Active = 0;
|
||||
short temp_atHome = 0;
|
||||
short temp_finished = 0;
|
||||
short lastPosition = 44;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (this->relativePawns[i] == -1) {
|
||||
temp_atBase++;
|
||||
continue;
|
||||
}
|
||||
// niedokończone...
|
||||
}
|
||||
}
|
||||
|
||||
void Player::sendToBase(short pawnNumber) {
|
||||
this->relativePawns[pawnNumber] = -1;
|
||||
this->pawnsActive--;
|
||||
@@ -81,9 +103,21 @@ void Player::sendToBoard(short pawnNumber) {
|
||||
void Player::unsafeMovePiece(short pawnNumber, short steps) {
|
||||
// to dopełnia obecną w Engine.cpp movePiece()
|
||||
// metoda jest "unsafe" ponieważ nie sprawdza danych, tylko ufa movePiece()
|
||||
this->relativePawns[pawnNumber] += steps;
|
||||
if (this->relativePawns[pawnNumber] >= 40) {
|
||||
if (this->relativePawns[pawnNumber] >= 39 && this->isPawnAtHome(pawnNumber)) {
|
||||
this->pawnsActive--;
|
||||
this->pawnsAtHome++;
|
||||
}
|
||||
this->relativePawns[pawnNumber] += steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if pawn is at home.
|
||||
*
|
||||
* @param[in] color Player's color
|
||||
* @param[in] pawnId The pawn's unique identifier
|
||||
*
|
||||
* @return True if pawn at home, false otherwise.
|
||||
*/
|
||||
bool Player::isPawnAtHome(short pawnId) {
|
||||
return this->relativePawns[pawnId] >= 44 - 4;
|
||||
}
|
||||
Reference in New Issue
Block a user