biquadris / model.cc
model.cc
Raw
#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;
        }
    }
}