Source

zorkish / SelectAdventureStage.hpp

/*
 * SelectAdventureStage.hpp
 *
 *  Created on: 20/08/2012
 *      Author: rhys
 */

#ifndef SELECTADVENTURESTAGE_HPP_
#define SELECTADVENTURESTAGE_HPP_

#include <stdexcept>
#include <fstream>
#include "AdventureStage.hpp"

class SelectAdventureStage : public ZorkishStage {
private:
    std::string message;

    static std::unique_ptr<World> test_world() {
        auto w = make_unique<World>();
        auto* sloc = new Location("Void World", "This world is simple and "
                "pointless. Used it to test Zorkish phase 1 spec.");
        sloc->inv.add(make_unique<Item>("delicious cake", Item::Ids {"cake"}));
        sloc->inv.add(make_unique<Item>("a rock", Item::Ids {"rock"}));
        w->add_location(0, sloc);
        return w;
    }

    static Location* load_location(std::string& name, std::ifstream& f) {
        std::string desc;
        getline(f, desc, '|');
        auto* loc = new Location(name, desc);
        while (f.peek() != '\n' && !f.eof()) { // peek sets eof
            std::string link;
            getline(f, link, ';');

            auto seploc = link.find('=');
            auto to = boost::lexical_cast<int>(
                    link.substr(seploc + 1, link.length()));
            loc->exits[link.substr(0, seploc)] = to;
        }
        return loc;
    }

    static void load_item(std::string& name, int location_id, std::ifstream& f,
            const std::unique_ptr<World>& w) {
        Item::Ids ids;
        while (f.peek() != '\n' && !f.eof()) {
            std::string identifier;
            getline(f, identifier, ';');
            ids.push_back(identifier);
        }
        // Obviously the following will crash and burn if the location hasn't
        // been defined yet.
        auto* location = w->get_location(location_id);
        location->inv.add(make_unique<Item>(name, ids));
    }

    static std::unique_ptr<World> load() {
        std::ifstream f;
        auto w = make_unique<World>();
        f.open("world.txt");
        while (!f.eof()) {
            char type;
            int id;
            std::string name;

            f >> type;
            f.ignore(1);
            f >> id;
            f.ignore(1);
            getline(f, name, '|');

            switch (type) {
            case 'L':
                w->add_location(id,
                        SelectAdventureStage::load_location(name, f));
                break;
            case 'I':
                SelectAdventureStage::load_item(name, id, f, w);
                break;
            default:
                throw std::runtime_error("Unknown entity type specified");
            }
        }
        return w;
    }

    GameStage::Status setup_adventure(ActiveStageManager& smgr,
            std::unique_ptr<World> world) {
        this->game.adventure()->setup(std::move(world), 0);
        smgr.set_next_stage(this->game.adventure().get());
        return GameStage::Status::FINISH;
    }

public:
    SelectAdventureStage(ZorkishGame& game) : ZorkishStage(game) {};

    virtual Status update(ActiveStageManager& smgr) {
        switch (this->input_int()) {
        case 1:
            return this->setup_adventure(smgr,
                    SelectAdventureStage::test_world());
        case 2:
            return this->setup_adventure(smgr, SelectAdventureStage::load());
        default:
            this->message = "Please select a number listed above.";
            break;
        }

        return GameStage::Status::CONTINUE;
    }

    virtual void draw() {
        using std::cout;
        cout << "===Select Adventure===\n";
        cout << "Choose your adventure:\n";
        cout << "1. Test world\n";
        cout << "2. Load from world.txt\n";
        if (!this->message.empty()) {
            cout << this->message << '\n';
            this->message.clear();
        }
        cout << "Select 1-2: ";
    }
};

#endif /* SELECTADVENTURESTAGE_HPP_ */