#include "wrap-vector.hpp" #include "wrap-string.hpp" #include "luastack.hpp" #include "util.hpp" #include "gui.hpp" #include "invocation.hpp" #include "world.hpp" #include "traceback.hpp" #include "luaconsole.hpp" #include "pprint.hpp" #include "printbuffer.hpp" #include "drivenengine.hpp" #include #include #include #include #include class TextGame : public DrivenEngine { private: using StringVec = LuaConsole::StringVec; UniqueWorld world_; LuaConsole console_; PrintChanneler print_channeler_; Gui gui_; int64_t actor_id_; void do_luainvoke_command(const StringVec &words) { world_->invoke(Invocation(Invocation::KIND_LUA, actor_id_, actor_id_, words[1])); } void do_luaprobe_command(const StringVec &words) { world_->snapshot(); stdostream() << world_->probe_lua(actor_id_, words[1]); world_->rollback(); } void do_syntax_command(const StringVec &words) { stdostream() << "Syntax Error: " << words[1] << std::endl; } void do_view_command(const StringVec &cmd) { stdostream() << world_->tangibles_near_debug_string(actor_id_, 100); } void do_menu_command(const StringVec &cmd) { int64_t place = sv::to_int64(cmd[1], actor_id_); world_->update_gui(actor_id_, place, &gui_); stdostream() << gui_.menu_debug_string(); } void do_choose_command(const StringVec &cmd) { eng::string action = gui_.get_action(sv::to_int64(cmd[1])); if (action == "") { stdostream() << "Invalid menu item #" << std::endl; return; } Invocation inv(Invocation::KIND_PLAN, actor_id_, gui_.place(), action); stdostream() << "Invoking: " << inv.debug_string() << std::endl; world_->invoke(inv); } void do_tick_command(const StringVec &cmd) { world_->invoke(Invocation(Invocation::KIND_TICK, actor_id_, actor_id_, "")); } void do_quit_command(const StringVec &cmd) { actor_id_ = 0; } void do_command(const StringVec &words) { if (words.empty()) return; else if (words[0] == "luainvoke") do_luainvoke_command(words); else if (words[0] == "luaprobe") do_luaprobe_command(words); else if (words[0] == "syntax") do_syntax_command(words); else if (words[0] == "view") do_view_command(words); else if (words[0] == "menu") do_menu_command(words); else if (words[0] == "quit") do_quit_command(words); else if (words[0] == "tick") do_tick_command(words); else if (words[0] == "choose") do_choose_command(words); else { stdostream() << "Unsupported command: " << words[0] << std::endl; } } void check_redirects() { World::Redirects redir = world_->fetch_redirects(); for (const auto &p : redir) { if (p.first == actor_id_) { actor_id_ = p.second; stdostream() << "Login actor ID: " << actor_id_ << std::endl; gui_.clear(0); } } } void event_init(int argc, char *argv[]) { world_.reset(new World(util::WORLD_TYPE_STANDALONE)); world_->update_source(get_lua_source()); world_->run_unittests(); actor_id_ = world_->create_login_actor(); stdostream() << "Login actor ID: " << actor_id_ << std::endl; get_stdio_channel()->set_prompt(console_.get_prompt()); } void event_update() { world_->update_source(get_lua_source()); while (true) { eng::string line = get_stdio_channel()->in()->readline(); if (line == "") break; console_.add(line); get_stdio_channel()->set_prompt(console_.get_prompt()); do_command(console_.get_command()); if (print_channeler_.channel(world_->get_printbuffer(actor_id_), stdostream())) { world_->invoke(print_channeler_.invocation(actor_id_)); } check_redirects(); if (actor_id_ == 0) { stop_driver(); break; } } } }; UniqueDrivenEngine make_TextGame() { return UniqueDrivenEngine(new TextGame); } static DrivenEngineReg reg_TextGame("textgame", make_TextGame);