biquadris / controller.cc
controller.cc
Raw
#include <fstream>
#include <sstream>
#include <istream>
#include "controller.h"
#include "model.h"
#include "view.h"

std::map<std::string, std::string> Controller::commands {
    {"left", "left"},
    {"right", "right"},
    {"down", "down"},
    {"clockwise", "clockwise"},
    {"counterclockwise", "counterclockwise"},
    {"drop", "drop"},
    {"levelup", "levelup"},
    {"leveldown", "leveldown"},
    {"norandom", "norandom"},
    {"random", "random"},
    {"sequence", "sequence"},
    {"hint", "hint"},
    {"I", "I"},
    {"J", "J"},
    {"L", "L"},
    {"O", "O"},
    {"S", "S"},
    {"Z", "Z"},
    {"T", "T"},
    {"restart", "restart"},
    {"rename", "rename"}
};

Controller::Controller(View &view, std::istream *input): input{input}, defaultInput{input}, view{view} {}

// Private
std::string Controller::findCommand(std::string keyword) {
    int counter = 0;
    int hilength = 0;
    int hilengthcount = 0;
    std::string command = "";
    for (auto key : commands) {
        bool isKey = false;
        int length = 0;
        for (size_t i = 0; i < key.first.length(); ++i) {
            if (key.second[i] != keyword[i]) {
                break;
            } else {
                ++length;
            }
        }
        if (length != 0) {
            ++counter;
            if (hilength < length) {
                isKey = true;
                hilength = length;
                hilengthcount = 1;
            } else if (hilength == length) {
                ++hilengthcount;
            }
        }
        std::string k = key.first;
        if (isKey) { 
            command = k;
        }
    }
    if (hilengthcount == 1) {
        return command;
    } else {
        return "";
    }
}

void Controller::getCommandInput() {
    std::string keyword, cmd;
    std::cout << view;
    while (true) {
        std::cout << "Player " << model->getCurrPlayer() << "'s turn: " << std::endl;
        if (!std::getline(*input, keyword)) break;
        std::istringstream ss(keyword);
        std::string second, third;
        ss >> keyword;
        ss >> second;
        ss >> third;

        int n = 0;
        // Parses multiplier prefix
        int i = 0;
        while (keyword[i] >= '0' && keyword[i] <= '9') {
            n = 10 * n + keyword[i] - '0';
            ++i;
        }
        keyword = keyword.substr(i);
        if (n == 0 && i == 0) n = 1;

        cmd = findCommand(keyword);
        if (cmd.empty()) {
            std::cout << "Invalid Command!" << std::endl;
        } else {
            if (cmd == "left") {
                model->move('l', n);
                std::cout << view;
            } else if (cmd == "right") {
                model->move('r', n);
                std::cout << view;
            } else if (cmd == "down") {
                model->move('d', n);
                std::cout << view;
            } else if (cmd == "clockwise") {
                model->rotate(true, n);
                std::cout << view;
            } else if (cmd == "counterclockwise") {
                model->rotate(false, n);
                std::cout << view;
            } else if (cmd == "drop") {
                model->drop(n);
                std::cout << view;
            } else if (cmd == "levelup") {
                for (int i = 0; i < n; ++i) {
                    model->levelUp();
                }
                std::cout << view;
            } else if (cmd == "leveldown") {
                for (int i = 0; i < n; ++i) {
                    model->levelDown();
                }
                std::cout << view;
            } else if (cmd == "norandom") {
                if (second != "") {
                    model->setRandom(false);
                    model->setSequence(second); 
                }
            } else if (cmd == "random") {
                model->setRandom(true);
            } else if (cmd == "sequence") {
                if (second != "") {
                    std::ifstream sequence;
                    sequence.open(second);
                    input = &sequence;
                    getCommandInput();
                    sequence.close();
                    input = defaultInput;
                }
            } else if (cmd == "I" || cmd == "J" || cmd == "L" || cmd == "O" ||
                       cmd == "S" || cmd == "Z" || cmd == "T") {
                // Replace with corresponding block type if possible
                model->replaceCurrBlock(cmd[0]);
                std::cout << view;
            } else if (cmd == "restart") {
                model->restart();
                std::cout << view;
            } else if (cmd == "hint") {
                model->hint();
                std::cout << view;
            } else if (cmd == "rename") {
                if (second != "" && third != "") {
                    std::string s = findCommand(second);
                    if (s != "") {
                        commands[s] = third;
                    }
                }
            }
        }
    }
}

void Controller::addModel(BiquadrisModel *model) {
    this->model = model;
}

void Controller::getSpecialActionCommand() {
    std::cout << "Enter a Special Action: " << std::endl;
    std::string cmd;
    while (true) {
        if (!std::getline(*input, cmd)) break;
        if (cmd == "blind") {
            model->addBlind();
            break;
        } else if (cmd == "heavy") {
            model->addHeavy();
            break;
        } else if (cmd == "force") {
            std::cout << "Choose a Block: ";
            char type;
            input->get(type);
            model->replaceCurrBlock(type, false);
            break;
        } else {
            std::cout << std::endl << "Special Action: blind, heavy, force" << std::endl;
        }
    }
}