Added invoke_plan, removed viewer
This commit is contained in:
@@ -15,7 +15,6 @@ CPP_FILES=\
|
|||||||
cpp/animqueue.cpp\
|
cpp/animqueue.cpp\
|
||||||
cpp/source.cpp\
|
cpp/source.cpp\
|
||||||
cpp/world.cpp\
|
cpp/world.cpp\
|
||||||
cpp/viewer.cpp\
|
|
||||||
cpp/textgame.cpp\
|
cpp/textgame.cpp\
|
||||||
cpp/main.cpp
|
cpp/main.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
LuaDefineType(Gui);
|
LuaDefineType(Gui);
|
||||||
|
|
||||||
void Gui::add_menu_item(const std::string &id, const std::string &label) {
|
void Gui::menu_item(const std::string &action, const std::string &label) {
|
||||||
GuiElt elt;
|
GuiElt elt;
|
||||||
elt.type_ = GuiElt::TYPE_MENU_ITEM;
|
elt.type_ = GuiElt::TYPE_MENU_ITEM;
|
||||||
elt.id_ = id;
|
elt.action_ = action;
|
||||||
elt.label_ = label;
|
elt.label_ = label;
|
||||||
elts_.push_back(elt);
|
elts_.push_back(elt);
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,11 @@ LuaDefine(gui_create, "c") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LuaDefine(gui_menu_item, "c") {
|
LuaDefine(gui_menu_item, "c") {
|
||||||
LuaArg lgui, lid;
|
LuaArg lgui, laction, llabel;
|
||||||
LuaStack LS(L, lgui, lid);
|
LuaStack LS(L, lgui, laction, llabel);
|
||||||
Gui *gui = LS.ckuserdata<Gui>(lgui);
|
Gui *gui = LS.ckuserdata<Gui>(lgui);
|
||||||
std::string id = LS.ckstring(lid);
|
std::string action = LS.ckstring(laction);
|
||||||
gui->add_menu_item(id, id);
|
std::string label = LS.ckstring(llabel);
|
||||||
|
gui->menu_item(action, label);
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ public:
|
|||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
std::string id_;
|
std::string action_;
|
||||||
std::string label_;
|
std::string label_;
|
||||||
|
|
||||||
GuiElt() {}
|
GuiElt() {}
|
||||||
public:
|
public:
|
||||||
~GuiElt() {}
|
~GuiElt() {}
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
const std::string &id() const { return id_; }
|
const std::string &action() const { return action_; }
|
||||||
const std::string &label() const { return label_; }
|
const std::string &label() const { return label_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
const EltVec &elts() const { return elts_; }
|
const EltVec &elts() const { return elts_; }
|
||||||
void clear() { elts_.clear(); }
|
void clear() { elts_.clear(); }
|
||||||
void add_menu_item(const std::string &id, const std::string &label);
|
void menu_item(const std::string &action, const std::string &label);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GUI_HPP
|
#endif // GUI_HPP
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// LUASNAP
|
// LUASNAP
|
||||||
//
|
//
|
||||||
// A lua interpreter that can be checkpointed (snapshotted).
|
// A lua interpreter that can be checkpointed (snapshotted). This makes it
|
||||||
// This makes it possible to roll the entire interpreter back
|
// possible to roll the entire interpreter back to a previously-snapshotted
|
||||||
// to a previously-snapshotted state.
|
// state.
|
||||||
//
|
//
|
||||||
// To accomplish this, we take advantage of the 'allocf' parameter
|
// To accomplish this, we take advantage of the 'allocf' parameter to
|
||||||
// to lua_newstate. This lets us hook the lua allocator, which
|
// lua_newstate. This lets us hook the lua allocator, which in turn lets us
|
||||||
// in turn lets us find every block of memory currently in use by
|
// find every block of memory currently in use by lua. To snapshot, we 'memcpy'
|
||||||
// lua. To snapshot, we 'memcpy' every block of memory
|
// every block of memory that lua is using into a buffer. To rollback, we just
|
||||||
// that lua is using into a buffer. To rollback, we just 'memcpy'
|
// 'memcpy' the data back.
|
||||||
// the data back.
|
|
||||||
//
|
//
|
||||||
// The current implementation is a proof-of-concept. It's quite
|
// The current implementation is a proof-of-concept. It's quite wasteful of
|
||||||
// wasteful of memory, roughly doubling the amount of RAM that
|
// memory, roughly doubling the amount of RAM that LUA uses. It's also not
|
||||||
// LUA uses. But it does demonstrate that this method of snapshot
|
// super-fast, since it allocates tons of tiny blocks. But it totally
|
||||||
// and rollback is feasible.
|
// works, so it demonstrate that this method of snapshot and rollback is
|
||||||
|
// feasible.
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef LUASNAP_HPP
|
#ifndef LUASNAP_HPP
|
||||||
#define LUASNAP_HPP
|
#define LUASNAP_HPP
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "gui.hpp"
|
#include "gui.hpp"
|
||||||
#include "viewer.hpp"
|
#include "world.hpp"
|
||||||
#include "traceback.hpp"
|
#include "traceback.hpp"
|
||||||
#include "textgame.hpp"
|
#include "textgame.hpp"
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
@@ -44,7 +44,7 @@ static void l_message(const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_lua(const std::string &exp) {
|
void TextGame::do_lua(const std::string &exp) {
|
||||||
lua_State *L = viewer_.state();
|
lua_State *L = world_->state();
|
||||||
int status = luaL_loadbuffer(L, exp.c_str(), exp.size(), "=stdin");
|
int status = luaL_loadbuffer(L, exp.c_str(), exp.size(), "=stdin");
|
||||||
assert(status == LUA_OK);
|
assert(status == LUA_OK);
|
||||||
globalL = L;
|
globalL = L;
|
||||||
@@ -81,8 +81,8 @@ void TextGame::do_view_command(const StringVec &cmd) {
|
|||||||
std::cerr << "v command (view) takes no arguments" << std::endl;
|
std::cerr << "v command (view) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int64_t id : viewer_.get_near()) {
|
for (int64_t id : world_->get_near(1, 100)) {
|
||||||
const Tangible *tan = viewer_.tangible_get(id);
|
const Tangible *tan = world_->tangible_get(id);
|
||||||
const AnimQueue &aq = tan->anim_queue_;
|
const AnimQueue &aq = tan->anim_queue_;
|
||||||
std::cerr << id << ": " << aq.get_graphic() << " " << aq.get_plane() << " " << aq.get_xyz() << std::endl;
|
std::cerr << id << ": " << aq.get_graphic() << " " << aq.get_plane() << " " << aq.get_xyz() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -98,8 +98,8 @@ void TextGame::do_menu_command(const StringVec &cmd) {
|
|||||||
std::cerr << "m command (menu) expects a tangible ID or defaults to 1" << std::endl;
|
std::cerr << "m command (menu) expects a tangible ID or defaults to 1" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gui_id_ = id;
|
gui_place_ = id;
|
||||||
viewer_.update_gui(id, &gui_);
|
world_->update_gui(1, id, &gui_);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (const GuiElt &elt : gui_.elts()) {
|
for (const GuiElt &elt : gui_.elts()) {
|
||||||
std::cerr << index << " " << elt.label() << std::endl;
|
std::cerr << index << " " << elt.label() << std::endl;
|
||||||
@@ -120,7 +120,9 @@ void TextGame::do_choose_command(const StringVec &cmd) {
|
|||||||
std::cerr << "No menu item #" << index << std::endl;
|
std::cerr << "No menu item #" << index << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cerr << "Choosing menu item: " << elts[index].id() << std::endl;
|
std::string action = elts[index].action();
|
||||||
|
std::cerr << "Invoking plan: " << action << std::endl;
|
||||||
|
world_->invoke_plan(1, gui_place_, action, &gui_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
||||||
@@ -128,7 +130,7 @@ void TextGame::do_snapshot_command(const StringVec &cmd) {
|
|||||||
std::cerr << "s command (snapshot) takes no arguments" << std::endl;
|
std::cerr << "s command (snapshot) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewer_.snapshot();
|
world_->snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_rollback_command(const StringVec &cmd) {
|
void TextGame::do_rollback_command(const StringVec &cmd) {
|
||||||
@@ -136,7 +138,7 @@ void TextGame::do_rollback_command(const StringVec &cmd) {
|
|||||||
std::cerr << "r command (rollback) takes no arguments" << std::endl;
|
std::cerr << "r command (rollback) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewer_.rollback();
|
world_->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_quit_command(const StringVec &cmd) {
|
void TextGame::do_quit_command(const StringVec &cmd) {
|
||||||
@@ -161,6 +163,8 @@ void TextGame::do_command(const StringVec &words) {
|
|||||||
|
|
||||||
void TextGame::run()
|
void TextGame::run()
|
||||||
{
|
{
|
||||||
|
world_.reset(new World);
|
||||||
|
world_->init_standalone();
|
||||||
console_.clear();
|
console_.clear();
|
||||||
while (true) {
|
while (true) {
|
||||||
console_.add_stdin();
|
console_.add_stdin();
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
#ifndef TEXTGAME_HPP
|
#ifndef TEXTGAME_HPP
|
||||||
#define TEXTGAME_HPP
|
#define TEXTGAME_HPP
|
||||||
|
|
||||||
#include "viewer.hpp"
|
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
|
#include "world.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class TextGame {
|
class TextGame {
|
||||||
private:
|
private:
|
||||||
using StringVec = LuaConsole::StringVec;
|
using StringVec = LuaConsole::StringVec;
|
||||||
Viewer viewer_;
|
std::unique_ptr<World> world_;
|
||||||
LuaConsole console_;
|
LuaConsole console_;
|
||||||
Gui gui_;
|
Gui gui_;
|
||||||
int64_t gui_id_;
|
int64_t gui_place_;
|
||||||
|
|
||||||
void do_view_command(const StringVec &cmd);
|
void do_view_command(const StringVec &cmd);
|
||||||
void do_menu_command(const StringVec &cmd);
|
void do_menu_command(const StringVec &cmd);
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
#include "viewer.hpp"
|
|
||||||
|
|
||||||
Viewer::Viewer() {
|
|
||||||
world_.reset(new World);
|
|
||||||
world_->init_standalone();
|
|
||||||
}
|
|
||||||
|
|
||||||
Viewer::~Viewer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t Viewer::get_player_id() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Viewer::update_gui(int64_t place, Gui *gui) {
|
|
||||||
world_->update_gui(get_player_id(), place, gui);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#ifndef VIEWER_HPP
|
|
||||||
#define VIEWER_HPP
|
|
||||||
|
|
||||||
#include "world.hpp"
|
|
||||||
#include "animqueue.hpp"
|
|
||||||
#include "gui.hpp"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class Viewer {
|
|
||||||
private:
|
|
||||||
std::unique_ptr<World> world_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Viewer();
|
|
||||||
~Viewer();
|
|
||||||
|
|
||||||
// Snapshot/rollback the lua state (temporary hack)
|
|
||||||
void snapshot() { world_->lua_snap_.snapshot(); }
|
|
||||||
void rollback() { world_->lua_snap_.rollback(); }
|
|
||||||
|
|
||||||
// Get the lua state for interaction.
|
|
||||||
//
|
|
||||||
lua_State *state() { return world_->state(); }
|
|
||||||
|
|
||||||
// Get the player ID of the current player.
|
|
||||||
//
|
|
||||||
int64_t get_player_id();
|
|
||||||
|
|
||||||
// Get the list of tangibles near the player.
|
|
||||||
//
|
|
||||||
std::vector<int64_t> get_near() { return world_->get_near(1, 100); }
|
|
||||||
|
|
||||||
// Get the specified tangible.
|
|
||||||
//
|
|
||||||
const Tangible *tangible_get(int64_t id) { return world_->tangible_get(id); }
|
|
||||||
|
|
||||||
// Update the GUI for the specified sprite.
|
|
||||||
//
|
|
||||||
// The gui passed in will be overwritten.
|
|
||||||
//
|
|
||||||
void update_gui(int64_t id, Gui *g);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // VIEWER_HPP
|
|
||||||
@@ -140,8 +140,8 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
|||||||
gui->clear();
|
gui->clear();
|
||||||
lua_State *L = state();
|
lua_State *L = state();
|
||||||
|
|
||||||
LuaVar actor, place, ugui, func, tangibles;
|
LuaVar actor, place, ugui, func, tangibles, mt, index;
|
||||||
LuaStack LS(L, actor, place, ugui, func, tangibles);
|
LuaStack LS(L, actor, place, ugui, func, tangibles, mt, index);
|
||||||
|
|
||||||
// Get the actor and place.
|
// Get the actor and place.
|
||||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
@@ -153,8 +153,17 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the interface closure.
|
// Get the interface closure.
|
||||||
// Use of 'gettable' instead of 'rawget' is deliberate.
|
LS.getmetatable(mt, place);
|
||||||
LS.gettable(func, place, "interface");
|
if (!LS.istable(mt)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LS.rawget(index, mt, "__index");
|
||||||
|
if (!LS.istable(index)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LS.rawget(func, index, "interface");
|
||||||
if (!LS.isfunction(func)) {
|
if (!LS.isfunction(func)) {
|
||||||
LS.result();
|
LS.result();
|
||||||
return;
|
return;
|
||||||
@@ -183,6 +192,66 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
|||||||
LS.result();
|
LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, Gui *gui) {
|
||||||
|
lua_State *L = state();
|
||||||
|
|
||||||
|
LuaVar actor, place, ugui, func, tangibles, mt, index, actions;
|
||||||
|
LuaStack LS(L, actor, place, ugui, func, tangibles, mt, index, actions);
|
||||||
|
|
||||||
|
// Get the actor and place.
|
||||||
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
|
LS.rawget(actor, tangibles, actor_id);
|
||||||
|
LS.rawget(place, tangibles, place_id);
|
||||||
|
if (!LS.istable(actor) || !LS.istable(place)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the action closure.
|
||||||
|
LS.getmetatable(mt, place);
|
||||||
|
if (!LS.istable(mt)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LS.rawget(index, mt, "__index");
|
||||||
|
if (!LS.istable(index)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LS.rawget(actions, index, "action");
|
||||||
|
if (!LS.istable(actions)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LS.rawget(func, actions, action);
|
||||||
|
if (!LS.isfunction(func)) {
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the userdata with the GUI pointer.
|
||||||
|
LS.newpointer<Gui>(ugui, gui, false);
|
||||||
|
|
||||||
|
// Call the action function.
|
||||||
|
lua_pushvalue(L, func.index());
|
||||||
|
lua_pushvalue(L, actor.index());
|
||||||
|
lua_pushvalue(L, place.index());
|
||||||
|
lua_pushvalue(L, ugui.index());
|
||||||
|
int status = traceback_pcall(L, 3, 0);
|
||||||
|
if (status != 0) {
|
||||||
|
gui->clear();
|
||||||
|
std::cerr << lua_tostring(L, -1);
|
||||||
|
LS.result();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nuke the userdata, in case somebody saved a pointer to it.
|
||||||
|
LS.clearuserdata(ugui);
|
||||||
|
|
||||||
|
// And we're done.
|
||||||
|
LS.result();
|
||||||
|
}
|
||||||
|
|
||||||
LuaDefine(tangible_get, "c") {
|
LuaDefine(tangible_get, "c") {
|
||||||
LuaArg id;
|
LuaArg id;
|
||||||
LuaRet database;
|
LuaRet database;
|
||||||
|
|||||||
@@ -112,12 +112,21 @@ public:
|
|||||||
//
|
//
|
||||||
void update_gui(int64_t actor_id, int64_t place_id, Gui *gui);
|
void update_gui(int64_t actor_id, int64_t place_id, Gui *gui);
|
||||||
|
|
||||||
|
// Invoke an action plan.
|
||||||
|
//
|
||||||
|
void invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, Gui *gui);
|
||||||
|
|
||||||
// fetch
|
// fetch
|
||||||
//
|
//
|
||||||
// Given a lua state, fetch the world model associated with
|
// Given a lua state, fetch the world model associated with
|
||||||
// that lua state.
|
// that lua state.
|
||||||
//
|
//
|
||||||
static World *fetch(lua_State *L);
|
static World *fetch(lua_State *L);
|
||||||
|
|
||||||
|
// Snapshot and rollback - temporary.
|
||||||
|
//
|
||||||
|
void snapshot() { lua_snap_.snapshot(); }
|
||||||
|
void rollback() { lua_snap_.rollback(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WORLD_HPP
|
#endif // WORLD_HPP
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
maketangible('player')
|
maketangible('player')
|
||||||
|
|
||||||
function player.interface(actor, place, gui)
|
function player.interface(actor, place, gui)
|
||||||
gui:menu_item("North")
|
gui:menu_item("north", "Go North")
|
||||||
gui:menu_item("South")
|
gui:menu_item("south", "Go South")
|
||||||
gui:menu_item("East")
|
gui:menu_item("east", "Go East")
|
||||||
gui:menu_item("West")
|
gui:menu_item("west", "Go West")
|
||||||
end
|
end
|
||||||
|
|
||||||
function player.action.north(actor, place, gui)
|
function player.action.north(actor, place, gui)
|
||||||
|
|||||||
Reference in New Issue
Block a user