check return values (movePiece), offload some logic into Player class

This commit is contained in:
2025-01-28 04:48:45 +01:00
parent c4a74531db
commit 2469c6e504
2 changed files with 206 additions and 73 deletions

View File

@@ -78,10 +78,16 @@ void Engine::nextTurn() {
// Wybieranie pionka // Wybieranie pionka
bool pickAPlace = false; bool pickAPlace = false;
bool isMovePossible = checkPossibleMoves(currentPlayer.getColor(), 6) > 0;
// Wylosowanie szóstki to specjalny przypadek // Wylosowanie szóstki to specjalny przypadek
if (diceRoll == 6) { if (diceRoll == 6) {
isMovePossible |= currentPlayer.pawnsAtBase > 0;
if (isMovePossible) {
std::string choice; std::string choice;
bool pawnMoved = false;
switch (currentPlayer.pawnsActive) { switch (currentPlayer.pawnsActive) {
// 0 pionków na planszy - musi wyjść pionkiem // 0 pionków na planszy - musi wyjść pionkiem
@@ -123,18 +129,40 @@ void Engine::nextTurn() {
if (currentPlayer.pawnsActive > 1) { if (currentPlayer.pawnsActive > 1) {
pickAPlace = true; pickAPlace = true;
break;
} else { } else {
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
<< diceRoll << " pol do przodu.\n"; // Sprawdź, czy gracz może ruszyć jedyny pionek o tyle pól do przodu
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
short* relativePawns = currentPlayer.getRelativePawns(); short* relativePawns = currentPlayer.getRelativePawns();
if (relativePawns[i] >= 0) 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) break;
} }
}
if (pawnMoved) {
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
<< diceRoll << " pol do przodu.\n";
this->pawnmoveBuffer.play(); this->pawnmoveBuffer.play();
this->board.smartSleep(2000); this->board.smartSleep(2000);
}
break; 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 { } else {
std::cout << "Podaj jedna z wymienionych odpowiedzi!\n> "; std::cout << "Podaj jedna z wymienionych odpowiedzi!\n> ";
@@ -151,8 +179,12 @@ void Engine::nextTurn() {
} }
}
} else { } else {
// Jeśli nie wypadło 6, gracz musi ruszyć któryś z pionków // Jeśli nie wypadło 6, gracz musi ruszyć któryś z pionków
bool pawnMoved = false;
switch (currentPlayer.pawnsActive) { switch (currentPlayer.pawnsActive) {
// 0 pionków na planszy // 0 pionków na planszy
@@ -167,15 +199,18 @@ void Engine::nextTurn() {
// dlatego ruszamy go za niego. // dlatego ruszamy go za niego.
pickAPlace = false; pickAPlace = false;
// TODO: znajdź ten pionek i ustaw selectedField na niego!!! // 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++) { for (int i = 0; i < 4; i++) {
short* relativePawns = currentPlayer.getRelativePawns(); short* relativePawns = currentPlayer.getRelativePawns();
if (relativePawns[i] >= 0) 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->pawnmoveBuffer.play();
this->board.smartSleep(2000); this->board.smartSleep(2000);
}
break; break;
// 2, 3, 4 pionki na planszy // 2, 3, 4 pionki na planszy
@@ -275,6 +310,22 @@ void Engine::nextTurn() {
return; 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. * @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. * @return Player's pawn ID, between 0 and 3.
*/ */
short Engine::fieldToFirstPawnId(short color, short field) { short Engine::fieldToFirstPawnId(short color, short field) {
// TODO for (int i = 0; i < 4; i++) {
return 0; 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] color Player's color
* @param[in] steps Amount of steps * @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. * @return Returns the number of pawns which can be moved given the step count.
*/ */
short Engine::checkPossibleMoves(short color, short steps) { short Engine::checkPossibleMoves(short color, short steps) {
// TODO short possibleMoves = 0;
return 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 Engine::spawnPiece(short color, short pawnId) {
short * relativePieces = players[color].getRelativePawns(); 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) { if (relativePieces[pawnId] == -1) {
players[color].sendToBoard(pawnId); players[color].sendToBoard(pawnId);
this->board.fields[relPosToField(color, relativePieces[pawnId])][pawnId] = color + 4; 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; short color = this->board.fields[field][i] - 4;
// Zaktualizuj liczbę pionków gracza // Zaktualizuj liczbę pionków gracza
this->players[color].pawnsActive -= 1; /*this->players[color].pawnsActive -= 1;
this->players[color].pawnsAtBase += 1; this->players[color].pawnsAtBase += 1;*/
players[color].sendToBase(i);
// Ustaw pionek na odpowiednie miejsce w bazie // Ustaw pionek na odpowiednie miejsce w bazie
this->board.fields[getPawnInitialPosition(color, i)][i] = color + 4; 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. * @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 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++) { for (int i = 0; i < 4; i++) {
if (this->board.fields[field][i] == color + 4) { if (this->board.fields[field][i] == color + 4) {
// Znaleźliśmy pionek do przesunięcia, teraz pytanie: // 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ć // - 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 // - w końcu, dopisujemy pionek bieżącego gracza
this->board.fields[newField][i] = color + 4; this->board.fields[newField][i] = color + 4;
this->players[this->currentPlayerIndex].unsafeMovePiece(i, steps); this->players[this->currentPlayerIndex].unsafeMovePiece(i, steps);

View File

@@ -53,18 +53,40 @@ void Player::movePawn(int pawnIndex, int steps) {
} }
} }
std::vector<Pawn>& Player::getPawns() {
return pawns;
}
bool Player::hasWon() const { 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() { short* Player::getRelativePawns() {
return this->relativePawns; 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) { void Player::sendToBase(short pawnNumber) {
this->relativePawns[pawnNumber] = -1; this->relativePawns[pawnNumber] = -1;
this->pawnsActive--; this->pawnsActive--;
@@ -81,9 +103,21 @@ void Player::sendToBoard(short pawnNumber) {
void Player::unsafeMovePiece(short pawnNumber, short steps) { void Player::unsafeMovePiece(short pawnNumber, short steps) {
// to dopełnia obecną w Engine.cpp movePiece() // to dopełnia obecną w Engine.cpp movePiece()
// metoda jest "unsafe" ponieważ nie sprawdza danych, tylko ufa movePiece() // metoda jest "unsafe" ponieważ nie sprawdza danych, tylko ufa movePiece()
this->relativePawns[pawnNumber] += steps; if (this->relativePawns[pawnNumber] >= 39 && this->isPawnAtHome(pawnNumber)) {
if (this->relativePawns[pawnNumber] >= 40) {
this->pawnsActive--; this->pawnsActive--;
this->pawnsAtHome++; 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;
} }