#include "model.h" #include "controller.h" #include "scoreboard.h" #include "board.h" #include "boardDecorator.h" #include "baseboard.h" #include "specialAction.h" #include "subscriptions.h" #include <string> #include <vector> #include <algorithm> #include "view.h" BiquadrisModel::BiquadrisModel(Controller *ctr, View *v, std::string seq1, std::string seq2, int playerCount, int width, int height, int seed, int level) : sb{std::make_unique<Scoreboard>(playerCount)}, ctr{ctr}, currentPlayer{0}, playerCount{playerCount}, specialActionActive{false} { attach(v); for (int i = 0; i < playerCount; ++i) { if (i == 0) boards.push_back(std::make_shared<BaseBoard>(width, height, seed, level, i, sb.get(), this, seq1)); else boards.push_back(std::make_shared<BaseBoard>(width, height, seed, level, i, sb.get(), this, seq2)); boards[i]->attach(this); boards[i]->attach(sb.get()); } sb->attach(this); notifyObservers(SubscriptionType::ModelInfoChange); } BiquadrisModel::~BiquadrisModel() {} void BiquadrisModel::setRandom(bool r) { boards[currentPlayer]->setRandom(r); } void BiquadrisModel::setSequence(std::string file) { boards[currentPlayer]->setSequence(file); } void BiquadrisModel::nextPlayer() { currentPlayer = (currentPlayer + 1) % playerCount; } int BiquadrisModel::getCurrPlayer() const noexcept { return currentPlayer + 1; } int BiquadrisModel::getPlayerCount() const noexcept { return playerCount; } void BiquadrisModel::move(char direction, int step) { boards[currentPlayer]->move(direction, step, 0); } void BiquadrisModel::drop(int amount) { for (int i = 0; i < amount; ++i) { boards[currentPlayer]->drop(); removeEffect(); } if (amount != 0) nextPlayer(); } void BiquadrisModel::rotate(bool isClockwise, int amount) { boards[currentPlayer]->rotate(isClockwise, amount, 0); } void BiquadrisModel::placeCurrBlock() { boards[currentPlayer]->placeCurrBlock(); } void BiquadrisModel::replaceCurrBlock(char type, bool safety) { boards[currentPlayer]->replaceCurrBlock(type, safety); } void BiquadrisModel::levelUp() { boards[currentPlayer]->levelUp(); notifyObservers(SubscriptionType::ModelInfoChange); } void BiquadrisModel::levelDown() { boards[currentPlayer]->levelDown(); notifyObservers(SubscriptionType::ModelInfoChange); } int BiquadrisModel::getLevel(int player) { return boards[player]->getLevel(); } char BiquadrisModel::getNextBlock(int player) { return boards[player]->getNextBlock(); } std::vector<SubscriptionType> BiquadrisModel::subType() { return std::vector<SubscriptionType> {SubscriptionType::ScoreChange, SubscriptionType::BoardModified, SubscriptionType::CellModified, SubscriptionType::SpecialAction, SubscriptionType::ModelInfoChange, SubscriptionType::PlayerLose, SubscriptionType::BlockDroppedByItself, SubscriptionType::HintChange }; } void BiquadrisModel::notify(Subject *whoNotified, SubscriptionType t) { std::vector<SubscriptionType> subs = subType(); if (t == SubscriptionType::SpecialAction) getSpecialActionCommand(); else if (t == SubscriptionType::BlockDroppedByItself) { removeEffect(); nextPlayer(); } else if (t == SubscriptionType::ModelInfoChange || t == SubscriptionType::PlayerLose) notifyObservers(t); else if (std::find(subs.begin(), subs.end(), t) != subs.end()) notifyObservers(whoNotified, t); } void BiquadrisModel::addBlind() { boards[currentPlayer] = std::make_shared<Blind>(boards[currentPlayer], this); } void BiquadrisModel::addHeavy() { boards[currentPlayer] = std::make_shared<Heavy>(boards[currentPlayer], this); } void BiquadrisModel::getSpecialActionCommand() { nextPlayer(); ctr->getSpecialActionCommand(); nextPlayer(); specialActionActive = true; } void BiquadrisModel::restart() { const int highScore = sb->getHighScore(); boards[currentPlayer]->restart(); sb->resetScore(currentPlayer); sb->setHighScore(highScore); } void BiquadrisModel::hint() { boards[currentPlayer]->hint(); } void BiquadrisModel::removeEffect() { if (specialActionActive && boards[currentPlayer]->getComponent() != nullptr) { boards[currentPlayer] = boards[currentPlayer]->getComponent(); boards[currentPlayer]->notifyObservers(SubscriptionType::BoardModified); if (boards[(currentPlayer + 1) % playerCount]->getComponent() == nullptr) { specialActionActive = false; } } }