Commit 9816cde9 authored by Jostein Bratlie's avatar Jostein Bratlie

Made the QML side of PlayerId typesafer and added optional return value for...

Made the QML side of PlayerId typesafer and added optional return value for engine player id and type queries.
parent e944431f
......@@ -90,14 +90,15 @@ namespace gameengine // resume namespace gameengine
{
using BitPieces = std::bitset<detail::computeBoardSize()>;
using BitBoard = std::array<BitPieces, 2>;
using BitPosSet = std::unordered_set<BitPos>;
enum class PlayerId : size_t { One = 0, Two = 1 };
enum class PlayerType { Human, AI };
enum class PlayerId : size_t { One = 0UL, Two = 1UL };
using PlayerIdOpt = std::optional<PlayerId>;
using PlayerIdSet = std::set<PlayerId>;
using BitPosSet = std::unordered_set<BitPos>;
enum class PlayerType { Human, AI };
using PlayerTypeOpt = std::optional<PlayerType>;
} // namespace gameengine
#endif // BASIC_TYPES_H
......@@ -12,7 +12,7 @@ namespace gameengine
struct PlayerStruct {
std::unique_ptr<PlayerInterface> obj;
PlayerType type;
PlayerTypeOpt type;
};
} // namespace detail
......@@ -30,10 +30,10 @@ namespace gameengine
bool performMoveForCurrentHuman(const BitPos&) override;
bool legalMovesCheck();
void think(const std::chrono::seconds&) override;
PlayerId currentPlayerId() const override;
PlayerType currentPlayerType() const override;
BitPieces pieces(const PlayerId&) const override;
void think(const std::chrono::seconds&) override;
PlayerIdOpt currentPlayerId() const override;
PlayerTypeOpt currentPlayerType() const override;
BitPieces pieces(const PlayerId&) const override;
const BitBoard& board() const override;
......
......@@ -36,10 +36,10 @@ namespace gameengine
virtual void think(const std::chrono::seconds& max_time) = 0;
/*! Return the player id of the current player */
virtual PlayerId currentPlayerId() const = 0;
virtual PlayerIdOpt currentPlayerId() const = 0;
/*! Return the player type of the current player */
virtual PlayerType currentPlayerType() const = 0;
virtual PlayerTypeOpt currentPlayerType() const = 0;
/*! Query the bitboard piece position set of a given player
* \param[in] player_id The given player
......
......@@ -14,9 +14,9 @@ namespace gameengine
void GameEngine::think(const std::chrono::seconds& /*time_limit*/) {}
PlayerId GameEngine::currentPlayerId() const { return {}; }
PlayerIdOpt GameEngine::currentPlayerId() const { return std::nullopt; }
PlayerType GameEngine::currentPlayerType() const { return {}; }
PlayerTypeOpt GameEngine::currentPlayerType() const { return std::nullopt; }
BitPieces GameEngine::pieces(const PlayerId& /*player_id*/) const
{
......
#include "gamemodel.h"
// qt
#include <QQmlEngine>
GameModel::GameModel(const gameengine::GameEngine& game_engine, QObject* parent)
: QAbstractListModel(parent), m_game_engine{game_engine}
{
......@@ -15,29 +18,27 @@ QVariant GameModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid()) return QVariant();
const size_t st_row = size_t(boardSize() - index.row() - 1);
const size_t st_row = size_t(boardSize() - index.row() - 1);
const auto piece_id = gameengine::BitPos(st_row);
const auto occupied = gameengine::utility::occupied(m_game_engine.board(), piece_id);
const auto occupied
= gameengine::utility::occupied(m_game_engine.board(), piece_id);
if (role == OccupiedRole)
return occupied;
else if (role == PlayerNrRole) {
if (!occupied) {
else if (role == PlayerIdRole) {
return QVariant(-1);
}
if (gameengine::utility::occupied(m_game_engine.pieces(gameengine::PlayerId::One),
piece_id)) {
return QVariant(uint(gameengine::PlayerId::One));
if (gameengine::utility::occupied(
m_game_engine.pieces(gameengine::PlayerId::One), piece_id)) {
return PlayerId::PlayerOne;
}
else if (gameengine::utility::occupied(
m_game_engine.pieces(gameengine::PlayerId::Two), piece_id)) {
return QVariant(uint(gameengine::PlayerId::Two));
return PlayerId::PlayerTwo;
}
return PlayerId::NoPlayer;
}
else if (role == PieceNrRole) {
......@@ -48,19 +49,22 @@ QVariant GameModel::data(const QModelIndex& index, int role) const
return QVariant();
}
int GameModel::boardSize() const { return int(gameengine::detail::computeBoardSize()); }
uint GameModel::currentPlayer() const {
int GameModel::boardSize() const
{
return int(gameengine::detail::computeBoardSize());
}
return uint(m_game_engine.currentPlayerId());
GameModel::PlayerId GameModel::currentPlayer() const
{
return convertPlayerId(m_game_engine.currentPlayerId());
}
QHash<int, QByteArray> GameModel::roleNames() const
{
QHash<int, QByteArray> role_names;
role_names[OccupiedRole] = "occupied";
role_names[PlayerNrRole] = "playernr";
role_names[PieceNrRole] = "piecenr";
role_names[PlayerIdRole] = "playerid";
role_names[PieceNrRole] = "piecenr";
return role_names;
}
......@@ -70,5 +74,24 @@ void GameModel::update()
beginResetModel();
endResetModel();
emit boardSizeChanged(gameengine::detail::computeBoardSize());
emit currentPlayerChanged(size_t(m_game_engine.currentPlayerId()));
emit currentPlayerChanged(currentPlayer());
}
GameModel::PlayerId GameModel::convertPlayerId(gameengine::PlayerIdOpt gm_id)
{
if (not gm_id) return PlayerId::NoPlayer;
switch (*gm_id) {
case gameengine::PlayerId::One:
return PlayerId::PlayerOne;
case gameengine::PlayerId::Two:
return PlayerId::PlayerTwo;
}
}
void GameModel::registerAsQmlType()
{
qmlRegisterUncreatableType<GameModel>(
"MyBoardGame", 1, 0, "GameModel",
"Provides Enums of the GameModel class.");
}
......@@ -14,19 +14,32 @@
#include <memory>
namespace gamemodel {
Q_NAMESPACE
using PlayerId = gameengine::PlayerId;
using PlayerType = gameengine::PlayerType;
Q_ENUM_NS(PlayerId)
Q_ENUM_NS(PlayerType)
};
class GameModel : public QAbstractListModel {
Q_OBJECT
public:
Q_PROPERTY(int boardSize READ boardSize NOTIFY boardSizeChanged)
Q_PROPERTY(uint currentPlayer READ currentPlayer NOTIFY currentPlayerChanged)
Q_PROPERTY(
PlayerId currentPlayer READ currentPlayer NOTIFY currentPlayerChanged)
enum ModelRoles {
OccupiedRole = Qt::UserRole + 1,
PlayerNrRole,
PlayerIdRole,
PieceNrRole
};
enum PlayerId { PlayerOne, PlayerTwo, NoPlayer };
Q_ENUM(PlayerId)
GameModel(const gameengine::GameEngine& game_engine,
QObject* parent = nullptr);
~GameModel() override = default;
......@@ -42,12 +55,19 @@ public slots:
private:
const gameengine::GameEngine& m_game_engine;
int boardSize() const;
uint currentPlayer() const;
int boardSize() const;
PlayerId currentPlayer() const;
signals:
void boardSizeChanged(size_t);
void currentPlayerChanged(size_t);
void currentPlayerChanged(PlayerId);
private:
static PlayerId convertPlayerId(gameengine::PlayerIdOpt gm_id);
public:
static void registerAsQmlType();
};
......
......@@ -20,6 +20,9 @@ int main(int argc, char** argv) try {
QCoreApplication::setOrganizationDomain("uit.no");
QCoreApplication::setApplicationName("STE6274 Board Game Engine -- Template Demo");
// Register QML types
GameModel::registerAsQmlType();
// Start application
GuiApplication app(argc, argv);
......
......@@ -3,6 +3,8 @@ import QtQuick.Layouts 1.13
import QtQuick.Controls 2.13
import QtQuick.Controls.Material 2.13
import MyBoardGame 1.0
ApplicationWindow {
id: root
......@@ -111,13 +113,15 @@ ApplicationWindow {
state: {
if (occupied) {
if(playernr == 0) return "player_one"
else if(playernr == 1) return "player_two"
if(playerid === GameModel.PlayerOne) return "player_one"
else if(playernr === GameModel.PlayerTwo) return "player_two"
else return "error"
}
else if(contains_mouse) {
if(gamemodel.currentPlayer === 0) return "player_one_hover"
else if(gamemodel.currentPlayer === 1) return "player_two_hover"
if(gamemodel.currentPlayer === GameModel.PlayerOne)
return "player_one_hover"
else if(gamemodel.currentPlayer === GameModel.PlayerTwo)
return "player_two_hover"
else return "error"
}
else return ""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment