UPD: Move computeDestination to LudoRules

This commit is contained in:
sebastian 2026-08-05 18:38:31 +02:00
parent a3bb54f041
commit 7426374b00
9 changed files with 59 additions and 73 deletions

View File

@ -287,8 +287,8 @@ add_library(GameLib STATIC
game/src/gameLayer/GameInput.cpp game/src/gameLayer/GameInput.cpp
game/src/gameLayer/GameInput.h game/src/gameLayer/GameInput.h
game/src/gameLayer/gameController/LudoGameControllerContext.h game/src/gameLayer/gameController/LudoGameControllerContext.h
game/src/ludo/LudoRules.cpp game/src/ludo/gameMode/LudoRules.cpp
game/src/ludo/LudoRules.h game/src/ludo/gameMode/LudoRules.h
game/src/ludo/gameMode/PiecePathBuilder.cpp game/src/ludo/gameMode/PiecePathBuilder.cpp
game/src/ludo/gameMode/PiecePathBuilder.h game/src/ludo/gameMode/PiecePathBuilder.h
game/src/ludo/gameMode/PathNode.h game/src/ludo/gameMode/PathNode.h

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include "gameMode/LudoRules.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
void ludo::LudoGameMode::sendCommand(const std::variant<MovePieceCommand, RollDiceCommand> &command) { void ludo::LudoGameMode::sendCommand(const std::variant<MovePieceCommand, RollDiceCommand> &command) {
@ -19,34 +20,6 @@ std::vector<ludo::LudoEvent> ludo::LudoGameMode::pollEvents() {
return events; return events;
} }
[[nodiscard]] std::optional<ludo::LudoGameMode::Destination> ludo::LudoGameMode::computeDestination(const Piece &piece, int diceValue) const {
switch (piece.state) {
case PieceState::AtHome:
return Destination{PieceState::OnTrack, getEntryOffset(piece.color)};
case PieceState::OnTrack: {
int distanceTraveled = (piece.position - getEntryOffset(piece.color) + kTrackLength) % kTrackLength;
int newDistance = distanceTraveled + diceValue;
if (newDistance <= kTrackLength - 1) {
return Destination{PieceState::OnTrack, (piece.position + diceValue) % kTrackLength};
}
int homeIndex = newDistance - kTrackLength;
if (homeIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
return Destination{homeIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, homeIndex};
}
case PieceState::InHomeStretch: {
int newIndex = piece.position + diceValue;
if (newIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
return Destination{newIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, newIndex};
}
case PieceState::Finished:
return std::nullopt; // nie bewegbar
}
return std::nullopt;
}
std::optional<int> ludo::LudoGameMode::findLowestHomeSlotPiece(PlayerColor color) const { std::optional<int> ludo::LudoGameMode::findLowestHomeSlotPiece(PlayerColor color) const {
for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) { for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) {
const auto& piece = m_gameState.m_pieces[i]; const auto& piece = m_gameState.m_pieces[i];
@ -61,7 +34,7 @@ ludo::LudoGameMode::MoveResult ludo::LudoGameMode::movePieceInternal(int pieceIn
Piece& piece = m_gameState.m_pieces[pieceIndex]; Piece& piece = m_gameState.m_pieces[pieceIndex];
int fromPosition = piece.position; int fromPosition = piece.position;
Destination destination = computeDestination(piece, diceValue).value(); Destination destination = LudoRules::computeDestination(m_gameState, piece, diceValue).value();
PieceState startState = piece.state; PieceState startState = piece.state;
PieceState targetState = destination.state; PieceState targetState = destination.state;
@ -182,7 +155,7 @@ std::vector<int> ludo::LudoGameMode::getMoveablePieceIndices(PlayerColor color,
const Piece& piece = m_gameState.getPieces()[i]; const Piece& piece = m_gameState.getPieces()[i];
if (piece.color != color) continue; if (piece.color != color) continue;
Destination dest = computeDestination(piece, diceValue).value(); Destination dest = LudoRules::computeDestination(m_gameState, piece, diceValue).value();
// Überschuss in der Zielgeraden abfangen: computeDestination liefert bei Überschuss // Überschuss in der Zielgeraden abfangen: computeDestination liefert bei Überschuss
// aktuell denselben Zustand zurück, wie unten in computeDestination definiert // aktuell denselben Zustand zurück, wie unten in computeDestination definiert
@ -201,7 +174,7 @@ std::vector<int> ludo::LudoGameMode::getMoveablePieceIndices(PlayerColor color,
std::optional<int> ludo::LudoGameMode::wouldCapture(int pieceIndex, int diceValue) const { std::optional<int> ludo::LudoGameMode::wouldCapture(int pieceIndex, int diceValue) const {
const auto& piece = m_gameState.m_pieces[pieceIndex]; const auto& piece = m_gameState.m_pieces[pieceIndex];
auto dest = computeDestination(piece, diceValue); auto dest = LudoRules::computeDestination(m_gameState, piece, diceValue);
if (dest.value().state != PieceState::OnTrack) return std::nullopt; if (dest.value().state != PieceState::OnTrack) return std::nullopt;
for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) { for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) {

View File

@ -15,19 +15,6 @@
#include "game/TurnBasedGameMode.h" #include "game/TurnBasedGameMode.h"
namespace ludo { namespace ludo {
struct PathNode {
PieceState state;
int position;
friend bool operator==(const PathNode& lhs, const PathNode& rhs) {
return lhs.state == rhs.state && lhs.position == rhs.position;
}
static inline void PrintTo(const PathNode& node, std::ostream* os) {
*os << "PathNode{state=" << static_cast<int>(node.state)
<< ", position=" << node.position << "}";
}
};
class LudoGameMode: public engine::TurnBasedGameMode<LudoCommand, LudoEvent, LudoGameState> { class LudoGameMode: public engine::TurnBasedGameMode<LudoCommand, LudoEvent, LudoGameState> {
public: public:
@ -56,13 +43,6 @@ namespace ludo {
PieceState targetState = PieceState::OnTrack; PieceState targetState = PieceState::OnTrack;
PieceState startState = PieceState::OnTrack; PieceState startState = PieceState::OnTrack;
}; };
struct Destination {
PieceState state;
int position;
};
std::optional<Destination> computeDestination(const Piece &piece, int diceValue) const;
[[nodiscard]] std::optional<int> findLowestHomeSlotPiece(PlayerColor color) const; [[nodiscard]] std::optional<int> findLowestHomeSlotPiece(PlayerColor color) const;
MoveResult movePieceInternal(int pieceIndex, int diceValue); MoveResult movePieceInternal(int pieceIndex, int diceValue);

View File

@ -1,9 +0,0 @@
//
// Created by sebastian on 05.08.26.
//
#include "LudoRules.h"
int ludo::LudoRules::getEntryOffset(PlayerColor color) {
return static_cast<int>(color) * 10;
}

View File

@ -42,7 +42,7 @@ void ludo::PiecePresenter::onPieceMoved(const ludo::PieceMovedEvent &event, cons
auto entity = m_pieceEntities[event.pieceIndex]; auto entity = m_pieceEntities[event.pieceIndex];
engine::animation::TransformAnimationComponent animationComponent; engine::animation::TransformAnimationComponent animationComponent;
std::vector<ludo::PathNode> path = PiecePathBuilder::computePath(piece.color, event.startState, event.fromPosition, event.targetState, event.toPosition); std::vector<PathNode> path = PiecePathBuilder::computePath(piece.color, event.startState, event.fromPosition, event.targetState, event.toPosition);
std::vector<glm::vec3> pathPositions; std::vector<glm::vec3> pathPositions;
for (const auto& node : path) { for (const auto& node : path) {
pathPositions.push_back(m_layout.getWorldPosition(piece.color, node.state, node.position)); pathPositions.push_back(m_layout.getWorldPosition(piece.color, node.state, node.position));

View File

@ -0,0 +1,37 @@
//
// Created by sebastian on 05.08.26.
//
#include "LudoRules.h"
int ludo::LudoRules::getEntryOffset(PlayerColor color) {
return static_cast<int>(color) * 10;
}
std::optional<ludo::Destination> ludo::LudoRules::computeDestination(const LudoGameState &state, const Piece &piece, int diceValue) {
switch (piece.state) {
case PieceState::AtHome:
return Destination{PieceState::OnTrack, getEntryOffset(piece.color)};
case PieceState::OnTrack: {
int distanceTraveled = (piece.position - getEntryOffset(piece.color) + kTrackLength) % kTrackLength;
int newDistance = distanceTraveled + diceValue;
if (newDistance <= kTrackLength - 1) {
return Destination{PieceState::OnTrack, (piece.position + diceValue) % kTrackLength};
}
int homeIndex = newDistance - kTrackLength;
if (homeIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
return Destination{homeIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, homeIndex};
}
case PieceState::InHomeStretch: {
int newIndex = piece.position + diceValue;
if (newIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
return Destination{newIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, newIndex};
}
case PieceState::Finished:
return std::nullopt; // nie bewegbar
}
return std::nullopt;
}

View File

@ -4,12 +4,18 @@
#ifndef COLORRACE_LUDORULES_H #ifndef COLORRACE_LUDORULES_H
#define COLORRACE_LUDORULES_H #define COLORRACE_LUDORULES_H
#include "LudoTypes.h" #include <optional>
#include "../LudoTypes.h"
#include "ludo/LudoGameState.h"
// LudoRules.h // LudoRules.h
namespace ludo { namespace ludo {
struct Destination {
PieceState state;
int position;
};
class LudoRules { class LudoRules {
public: public:
// Alles hier: reine Funktionen, keine Member, kein Zustand. // Alles hier: reine Funktionen, keine Member, kein Zustand.
@ -17,13 +23,12 @@ namespace ludo {
static int getEntryOffset(PlayerColor color); static int getEntryOffset(PlayerColor color);
static std::optional<Destination> computeDestination(const LudoGameState& state,
const Piece& piece, int diceValue);
}; };
struct Destination {
PieceState state;
int position;
};
} // namespace ludo } // namespace ludo

View File

@ -7,7 +7,7 @@
#include <format> #include <format>
#include "ludo/LudoGameMode.h" #include "ludo/LudoGameMode.h"
#include "ludo/LudoRules.h" #include "LudoRules.h"
namespace { namespace {
int stateOrder(ludo::PieceState state) { int stateOrder(ludo::PieceState state) {
@ -21,7 +21,7 @@ namespace {
} }
} }
std::vector<ludo::PathNode> ludo::PiecePathBuilder::computePath(PlayerColor color, PieceState startingState, std::vector<PathNode> ludo::PiecePathBuilder::computePath(PlayerColor color, PieceState startingState,
int startPosition, PieceState targetState, int targetPosition) { int startPosition, PieceState targetState, int targetPosition) {
auto errorContext = [&]() { auto errorContext = [&]() {
return std::format( return std::format(

View File

@ -6,8 +6,8 @@
#define COLORRACE_PIECEPATHBUILDER_H #define COLORRACE_PIECEPATHBUILDER_H
#include <vector> #include <vector>
#include "PathNode.h" #include "PathNode.h"
#include "ludo/LudoGameMode.h"
#include "ludo/LudoTypes.h" #include "ludo/LudoTypes.h"
@ -15,7 +15,7 @@ namespace ludo {
class PiecePathBuilder { class PiecePathBuilder {
public: public:
static std::vector<ludo::PathNode> computePath(PlayerColor color, PieceState startingState, int startPosition, PieceState targetState, int targetPosition); static std::vector<PathNode> computePath(PlayerColor color, PieceState startingState, int startPosition, PieceState targetState, int targetPosition);
}; };
} }