Commits

Rhys ! committed 654633f Draft

implemented locations, movement and world loading (Spike 7)

Comments (0)

Files changed (13)

 								<option defaultValue="false" id="llvm.c.link.option.nativeCBackEnd.697787166" name="Create native binary (with C backend code generator)" superClass="llvm.c.link.option.nativeCBackEnd" valueType="boolean"/>
 								<option id="llvm.c.link.option.libs.2047303032" name="Libraries (-l)" superClass="llvm.c.link.option.libs" valueType="libs">
 									<listOptionValue builtIn="false" value="stdc++"/>
-									<listOptionValue builtIn="false" value="ncurses"/>
 								</option>
 								<option id="llvm.c.link.option.paths.1743481513" name="Library search path (-L)" superClass="llvm.c.link.option.paths" valueType="libPaths">
 									<listOptionValue builtIn="false" value="/usr/lib"/>
-									<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6"/>
 									<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6/"/>
 								</option>
 								<inputType id="cdt.managedbuild.tool.llvm.c.linker.input.2024826335" superClass="cdt.managedbuild.tool.llvm.c.linker.input">
 									<listOptionValue builtIn="false" value="stdc++"/>
 								</option>
 								<option id="llvm.c.link.option.paths.56092692" name="Library search path (-L)" superClass="llvm.c.link.option.paths" valueType="libPaths">
-									<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6"/>
 									<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6/"/>
 								</option>
 								<inputType id="cdt.managedbuild.tool.llvm.c.linker.input.1256476665" superClass="cdt.managedbuild.tool.llvm.c.linker.input">

ActiveStageManager.hpp

     std::stack<GameStage*> stage_stack;
 
 public:
-    bool ready() {
+    bool ready() const {
         return !this->stage_stack.empty();
     }
 

AdventureStage.hpp

+/*
+ * AdventureStage.hpp
+ *
+ *  Created on: 20/08/2012
+ *      Author: rhys
+ */
+
+#ifndef ADVENTURESTAGE_HPP_
+#define ADVENTURESTAGE_HPP_
+
+#include <boost/algorithm/string/case_conv.hpp>
+#include "HighScoreStage.hpp"
+#include "Player.hpp"
+#include "util.cpp"
+#include "World.hpp"
+
+class AdventureStage : public ZorkishStage {
+private:
+    std::string message;
+    std::unique_ptr<World> world;
+    Player player;
+    int moves;
+    bool hiscore;
+
+    void pick_up(std::string name) {
+        std::stringstream ss;
+        auto it = this->player.current_location()->inv.take(name);
+        if (it) {
+            ss << "You pick up " << it->short_name() << ".";
+            this->player.inv.add(std::move(it));
+        } else {
+            ss << "There is no " << name << " here.";
+        }
+
+        this->message = ss.str();
+    }
+
+    void drop(std::string name) {
+        std::stringstream ss;
+        auto it = this->player.inv.take(name);
+        if (it) {
+            ss << "You drop " << it->short_name() << ".";
+            this->player.current_location()->inv.add(std::move(it));
+        } else {
+            ss << "You're not carrying a " << name << ".";
+        }
+
+        this->message = ss.str();
+    }
+
+    void look() {
+        this->message = this->player.current_location()->long_desc();
+    }
+
+    void go(std::string dirn) {
+        auto it = this->player.current_location()->exits.find(dirn);
+        if (it != this->player.current_location()->exits.end()) {
+            this->player.move(this->world->get_location((*it).second));
+            this->look();
+        } else {
+            this->message = "You can't go " + dirn + " from here.";
+        }
+    }
+
+public:
+    AdventureStage(ZorkishGame& game)
+            : ZorkishStage(game) { }
+
+    void setup(std::unique_ptr<World> world, int starting_location) {
+        auto* start = world->get_location(starting_location);
+        this->world.swap(world);
+        this->message = start->long_desc();
+        this->moves = 0;
+        this->player = Player(start);
+        this->hiscore = false;
+    }
+
+    virtual Status update(ActiveStageManager& smgr) {
+        if (!this->player.alive) {
+            if (this->hiscore) {
+                auto& hs = this->game.high_score();
+                hs->set_score(10, this->moves, "Test Adventure");
+                smgr.set_next_stage(hs.get());
+            }
+
+            return GameStage::Status::FINISH;
+        }
+
+        std::string cmd;
+        std::string params;
+        std::cin >> cmd;
+        getline(std::cin, params);
+        boost::to_upper(cmd);
+        if (params.empty()) {
+            if (cmd == "QUIT") {
+                this->message = "Your adventure has ended without fame or fortune.";
+                this->player.alive = false;
+            } else if (cmd == "HISCORE") {
+                this->message = "You have entered the magic word and will now see the \"New High Score\" screen.";
+                this->hiscore = true;
+                this->player.alive = false;
+            } else if (cmd == "LOOK") {
+                this->look();
+            } else if (cmd == "INV") {
+                this->message = this->player.inv.list("Inventory:", "\n  * ", "You aren't carrying anything.");
+            } else {
+                this->message = "I don't know how to do that.";
+            }
+        } else {
+            if (cmd == "TAKE") {
+                this->pick_up(params.substr(1, params.size() - 1));
+            } else if (cmd == "DROP") {
+                this->drop(params.substr(1, params.size() - 1));
+            } else if (cmd == "GO") {
+                this->go(params.substr(1, params.size() - 1));
+            } else {
+                this->message = "I don't know how to do that.";
+            }
+        }
+
+        this->moves++;
+        return GameStage::Status::CONTINUE;
+    }
+
+    virtual void draw() {
+        using std::cout;
+        if (!this->message.empty()) {
+            cout << this->message << '\n';
+            this->message.clear();
+        }
+        if (this->player.alive) {
+            cout << ":> ";
+        }
+    }
+};
+
+#endif /* ADVENTURESTAGE_HPP_ */
         cout << "===HELP===\n";
         cout << "The following commands are supported:\n\n";
         cout << "drop [item]\n";
+        cout << "go [direction]\n";
         cout << "hiscore\n";
         cout << "take [item]\n";
         cout << "quit\n";
 #ifndef INVENTORY_HPP_
 #define INVENTORY_HPP_
 
+#include <algorithm>
 #include <list>
 #include <memory>
 #include "Item.hpp"
 public:
     typedef std::list<std::unique_ptr<Item>>::const_iterator const_iterator;
 
+    std::string list(const std::string prefix, const std::string separator,
+            const std::string orelse) const {
+        if (this->items.empty()) {
+            return orelse;
+        } else {
+            std::stringstream ss;
+            ss << prefix;
+            for (const auto& item : this->items) {
+                ss << separator << item->short_name();
+            }
+            return ss.str();
+        }
+    }
+
     bool empty() const {
         return this->items.empty();
     }
     Inventory::const_iterator cend() const {
         return this->items.cend();
     }
-
-    void for_each(std::function<void(const std::unique_ptr<Item>&)> f) const {
-        std::for_each(this->cbegin(), this->cend(), f);
-    }
 };
 
 
 #define ITEM_HPP_
 
 #include <algorithm>
-#include <functional>
 #include <vector>
 #include <boost/algorithm/string/predicate.hpp>
 
 class Item {
+public:
+    typedef std::vector<std::string> Ids;
+
 private:
     std::string _short_name;
-    std::vector<std::string> ids;
+    Ids ids;
 
 public:
     // Use std::move for names
-    Item(std::string short_name, std::vector<std::string> ids) :
+    Item(std::string short_name, Ids ids) :
         _short_name(short_name), ids(ids) {};
 
     Item(std::string short_name, std::initializer_list<std::string> ids) :
-        _short_name(short_name), ids(std::vector<std::string>(ids)) {};
+        _short_name(short_name), ids(Ids(ids)) {};
 
     bool identifies_as(const std::string& id) {
         return boost::iequals(this->_short_name, id) ||
+/*
+ * Location.hpp
+ *
+ *  Created on: 04/09/2012
+ *      Author: rhys
+ */
+
+#ifndef LOCATION_HPP_
+#define LOCATION_HPP_
+
+#include <map>
+
+class Location {
+private:
+    std::string list_exits() const {
+        using std::begin; using std::end;
+        if (this->exits.empty()) {
+            return "\nThere are no exits leading from this location.";
+        } else {
+            std::stringstream ss;
+            for (const auto& pair : this->exits) {
+                ss << "\n *  " << pair.first;
+            }
+            return "\nExits:" + ss.str();
+        }
+    }
+
+public:
+    std::string name;
+    std::string description;
+    std::map<std::string, int> exits;
+    Inventory inv;
+
+    Location(std::string name, std::string description)
+            : name(name), description(description) {}
+
+    std::string long_desc() const {
+        return name + "\n\n" + description +
+                this->inv.list("\nItems:", "\n  * ", "") +
+                this->list_exits();
+    }
+};
+
+
+#endif /* LOCATION_HPP_ */
 #define PLAYER_HPP_
 
 #include "Inventory.hpp"
+#include "Location.hpp"
 
 class Player {
+private:
+    Location* c_location = nullptr;
+
 public:
     Inventory inv;
+    bool alive = true;
+
+    Player() {}
+    Player(Location* starting_location) : c_location(starting_location) {}
+
+    Location* current_location() const { return this->c_location; }
+    void move(Location* to) { this->c_location = to; }
 };
 
 

SelectAdventureStage.hpp

 #ifndef SELECTADVENTURESTAGE_HPP_
 #define SELECTADVENTURESTAGE_HPP_
 
-#include "TestAdventure.hpp"
+#include <fstream>
+#include "AdventureStage.hpp"
 
 class SelectAdventureStage : public ZorkishStage {
 private:
     std::string message;
 
+    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;
+    }
+
+    std::unique_ptr<World> load() {
+        std::ifstream f;
+        auto w = make_unique<World>();
+        f.open("world.txt");
+        while (!f.eof()) {
+            int id;
+            f >> id;
+            f.ignore(1, '|');
+            std::string name;
+            getline(f, name, '|');
+            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;
+            }
+            w->add_location(id, loc);
+        }
+        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:
-            smgr.set_next_stage(this->game.test_adventure().get());
-            return GameStage::Status::FINISH;
+            return this->setup_adventure(smgr, this->test_world());
+        case 2:
+            return this->setup_adventure(smgr, this->load());
         default:
             this->message = "Please select a number listed above.";
             break;
         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-1: ";
+        cout << "Select 1-2: ";
     }
 };
 

TestAdventure.hpp

-/*
- * TestAdventure.hpp
- *
- *  Created on: 20/08/2012
- *      Author: rhys
- */
-
-#ifndef TESTADVENTURE_HPP_
-#define TESTADVENTURE_HPP_
-
-#include <iostream>
-#include <boost/algorithm/string/case_conv.hpp>
-#include "HighScoreStage.hpp"
-#include "Player.hpp"
-#include "util.cpp"
-
-class TestAdventure : public ZorkishStage {
-private:
-    std::string message;
-    Inventory world_inv;
-    Player player;
-    int moves;
-    bool alive;
-    bool hiscore;
-
-    void pick_up(std::string name) {
-        std::stringstream ss;
-        auto it = this->world_inv.take(name);
-        if (it) {
-            ss << "You pick up " << it->short_name() << ".";
-            this->player.inv.add(std::move(it));
-        } else {
-            ss << "There is no " << name << " here.";
-        }
-
-        this->message = ss.str();
-    }
-
-    void drop(std::string name) {
-        std::stringstream ss;
-        auto it = this->player.inv.take(name);
-        if (it) {
-            ss << "You drop " << it->short_name() << ".";
-            this->world_inv.add(std::move(it));
-        } else {
-            ss << "You're not carrying a " << name << ".";
-        }
-
-        this->message = ss.str();
-    }
-
-    void list_items(const Inventory& inv) {
-        if (inv.empty()) {
-            this->message = "There is nothing there.";
-            return;
-        }
-
-        std::stringstream ss;
-        inv.for_each([&](const std::unique_ptr<Item>& item)
-                {ss << item->short_name() << '\n';});
-        this->message = ss.str();
-        this->message.resize(this->message.size() - 1);
-    }
-
-public:
-    TestAdventure(ZorkishGame& game) : ZorkishStage(game) {
-        this->cleanup();
-    }
-
-    virtual Status update(ActiveStageManager& smgr) {
-        if (!this->alive) {
-            if (this->hiscore) {
-                auto& hs = this->game.high_score();
-                hs->set_score(10, this->moves, "Test Adventure");
-                smgr.set_next_stage(hs.get());
-            }
-
-            return GameStage::Status::FINISH;
-        }
-
-        std::string cmd;
-        std::string params;
-        std::cin >> cmd;
-        getline(std::cin, params);
-        boost::to_upper(cmd);
-        if (params.empty()) {
-            if (cmd == "QUIT") {
-                this->message = "Your adventure has ended without fame or fortune.";
-                this->alive = false;
-            } else if (cmd == "HISCORE") {
-                this->message = "You have entered the magic word and will now see the \"New High Score\" screen.";
-                this->hiscore = true;
-                this->alive = false;
-            } else if (cmd == "LOOK") {
-                this->list_items(this->world_inv);
-            } else if (cmd == "INV") {
-                this->list_items(this->player.inv);
-            } else {
-                this->message = "I don't know how to do that.";
-            }
-        } else {
-            if (cmd == "TAKE") {
-                this->pick_up(params.substr(1, params.size() - 1));
-            } else if (cmd == "DROP") {
-                this->drop(params.substr(1, params.size() - 1));
-            } else {
-                this->message = "I don't know how to do that.";
-            }
-        }
-
-        this->moves++;
-        return GameStage::Status::CONTINUE;
-    }
-
-    virtual void draw() {
-        using std::cout;
-        if (!this->message.empty()) {
-            cout << this->message << '\n';
-            this->message.clear();
-        }
-        if (this->alive) {
-            cout << ":> ";
-        }
-    }
-
-    virtual void cleanup() {
-        this->message = "Welcome to Zorkish: Void World\nThis world is simple and pointless. Used it to test Zorkish phase 1 spec.";
-        this->moves = 0;
-        this->alive = true;
-        this->hiscore = false;
-        this->player = Player();
-        this->world_inv = Inventory();
-        this->world_inv.add(make_unique<Item>("delicious cake", std::vector<std::string> {"cake"}));
-        this->world_inv.add(make_unique<Item>("a rock", std::vector<std::string> {"rock"}));
-    }
-};
-
-#endif /* TESTADVENTURE_HPP_ */
+/*
+ * World.hpp
+ *
+ *  Created on: 04/09/2012
+ *      Author: rhys
+ */
+
+#ifndef WORLD_HPP_
+#define WORLD_HPP_
+
+#include "Location.hpp"
+
+class World {
+private:
+    // GCC doesn't have a working std::map for a value w/ move semantics
+    std::map<int, Location*> locations;
+
+public:
+    ~World() {
+        for (auto& pair : locations) {
+            delete pair.second;
+        }
+    }
+
+    // Obtains ownership of location
+    void add_location(int id, Location* location) {
+        this->locations[id] = location;
+    }
+
+    Location* get_location(int id) {
+        auto it = this->locations.find(id);
+        if (it != this->locations.end()) {
+            return (*it).second;
+        } else {
+            return nullptr;
+        }
+    }
+};
+
+
+#endif /* WORLD_HPP_ */
     return this->select_adv_stg;
 }
 
-const std::unique_ptr<TestAdventure>& ZorkishGame::test_adventure() {
+const std::unique_ptr<AdventureStage>& ZorkishGame::adventure() {
     if (!this->test_adv_stg) {
-        this->test_adv_stg.reset(new TestAdventure(*this));
+        this->test_adv_stg.reset(new AdventureStage(*this));
     }
     return this->test_adv_stg;
 }
 class HighScoreStage;
 class MainMenuStage;
 class SelectAdventureStage;
-class TestAdventure;
+class AdventureStage;
 
 class ZorkishGame {
 private:
     std::unique_ptr<HighScoreStage> high_score_stg;
     std::unique_ptr<MainMenuStage> main_menu_stg;
     std::unique_ptr<SelectAdventureStage> select_adv_stg;
-    std::unique_ptr<TestAdventure> test_adv_stg;
+    std::unique_ptr<AdventureStage> test_adv_stg;
 
 public:
     ZorkishGame();
     const std::unique_ptr<HighScoreStage>& high_score();
     const std::unique_ptr<MainMenuStage>& main_menu();
     const std::unique_ptr<SelectAdventureStage>& select_adventure();
-    const std::unique_ptr<TestAdventure>& test_adventure();
+    const std::unique_ptr<AdventureStage>& adventure();
 };
 
 #endif /* ZORKISH_HPP_ */