diff --git a/src/sdl-instead/game.c b/src/sdl-instead/game.c index 2309b46..80948f2 100644 --- a/src/sdl-instead/game.c +++ b/src/sdl-instead/game.c @@ -408,8 +408,9 @@ int game_save(int nr) p = instead_cmd(cmd); if (p) free(p); - if (!instead_bretval(1)) { + if (!instead_bretval(1) || !p) { instead_clear(); + game_menu(menu_warning); return -1; } instead_clear(); diff --git a/stead/dbg.lua b/stead/dbg.lua index ec90cdb..3ac8ea9 100644 --- a/stead/dbg.lua +++ b/stead/dbg.lua @@ -6,6 +6,7 @@ require "input" function disp_obj() local v = obj{ nam = 'disp', + act = true, dsc = function(s) local r = s._txt s._txt = nil; @@ -25,6 +26,7 @@ dump_obj = function(w) local rc='' for i,o in pairs(w) do if rc ~='' then rc = rc..'^' end + if isCode(o) then o = stead.string.format("code [[%s]]", stead.functions[o].code); end rc = stead.cat(rc, stead.par(' ', 'Key:'..tostring(i), 'Val:'..tostring(deref(o)))); end @@ -32,11 +34,15 @@ dump_obj = function(w) return true; end +dbg_here = function() + return debug_tool._here +end + list_objects = function() local i,o - local rc = stead.par(' ', 'Room:'..tostring(deref(from())), - 'Nam:'..tostring(call(from(),'nam'))); - for i,o in opairs(objs(from())) do + local rc = stead.par(' ', 'Room:'..tostring(deref(dbg_here())), + 'Nam:'..tostring(call(dbg_here(),'nam'))); + for i,o in opairs(objs(dbg_here())) do rc = rc..'^'; o = ref(o) rc = stead.cat(rc, stead.par(' ', 'Id:'..tostring(o.id), @@ -81,11 +87,8 @@ execute_cmd = room { end return back(); end, - act = function(s, w) - return back(); - end, - obj = { inp('{Enter cmd}: ', 'return "Hello World!"'), - vobj(1, 'Back', '^{Back}'), + obj = { inp('inp', '{Enter cmd}: ', 'return "Hello World!"'), + obj { nam = 'Back', dsc = '^{Back}', act = code [[ back() ]]}, new [[ disp_obj() ]], } } @@ -96,31 +99,19 @@ dump_object = room { forcedsc = true, dsc = "Enter object name here to dump.", inp_enter = function(s) - if type(s.obj[1]._txt) == 'string' then - return dump_obj(s.obj[1]._txt); + local w = s.obj[1]._txt + if type(w) == 'string' then + if not ref(w) then w = objs(dbg_here()):srch(w); end + return dump_obj(w); end return back(); end, - act = function(s, w) - if w == 1 then - return back(); - elseif w == 2 then - return dump_obj(from(from())); - elseif w == 3 then - return dump_obj(me()); - elseif w == 4 then - return dump_obj(game.lifes); - elseif w == 5 then - return dump_obj(ways(from(from()))); - end - - end, - obj = { inp('{Enter object}: ', 'main'), - vobj(2, 'Here', '^{Dump here}'), - vobj(3, 'Player', '^{Dump player}'), - vobj(4, 'Lifes', '^{Dump lifes}'), - vobj(5, 'Ways', '^{Dump ways}'), - vobj(1, 'Back', '^{Back}'), + obj = { inp('inp', '{Enter object}: ', 'main'), + obj{nam = 'Here', dsc = '^{Dump here}', act = code[[ return dump_obj(dbg_here())]]}, + obj{nam = 'Player',dsc = '^{Dump player}', act = code[[ return dump_obj(me())]]}, + obj{nam = 'Lifes', dsc = '^{Dump lifes}', act = code[[ return dump_obj(game.lifes)]]}, + obj{nam = 'Ways', dsc = '^{Dump ways}', act = code[[ return dump_obj(ways(dbg_here()))]]}, + obj{nam = 'Back', dsc = '^{Back}', act = code [[ return back() ]] }, new[[ disp_obj() ]]} } @@ -171,14 +162,17 @@ drop_object = dlg { for k,v in pairs(_G) do if isObject(v) and not isRoom(v) and not isPlayer(v) and not v.debug and have(v) then local n = call(v, 'nam'); - put (phr(k, true, 'drop("'..k..'","'..deref(from())..'")'), s) + put (phr(k, true, 'drop("'..k..'","'..deref(dbg_here())..'")'), s) end end put (phr('Back', true, 'return back()'), s) end } function dbg_exit() - local r = call(from(), 'dsc'); + local r + if game.version < "1.2.0" then + r = call(dbg_here(), 'dsc'); + end return par ('^^', back(), r); end debug_dlg = dlg { @@ -204,10 +198,13 @@ debug_tool = menu { forcedsc = true, nam = txtb('debug'), inv = function(s) - debug_dlg.__from__ = deref(here()); + if here().debug then + return nil, true --nothing todo + end + debug_dlg.__from__ = here(); + s._here = here(); me().where = 'debug_dlg'; -- force to go - local r = stead.par('^^', call(debug_dlg, 'enter'), call(debug_dlg, 'dsc')); - return r; + return goto(self.where); end, }; diff --git a/stead/goto.lua b/stead/goto.lua index 54a88d0..a0db3b0 100644 --- a/stead/goto.lua +++ b/stead/goto.lua @@ -31,7 +31,7 @@ go = function (self, where, back) if not isVroom(ref(where)) and not stead.in_exit_call then stead.in_exit_call = true -- to break recurse - v,r = call(ref(self.where), 'exit', where); + v,r = call(ref(self.where), 'exit', ref(where)); stead.in_exit_call = nil if r == false then return v, ret(r) @@ -50,7 +50,7 @@ go = function (self, where, back) end if not jump and (not back or not isDialog(ref(was)) or isDialog(ref(where))) then - v, r = call(ref(where), 'enter', deref(was)); + v, r = call(ref(where), 'enter', ref(was)); if r == false then self.where = was; return par('^^', res, v), ret(r) @@ -75,14 +75,14 @@ go = function (self, where, back) self.where = was stead.in_onexit_call = true - v = call(ref(was), 'left', deref(to)); + v = call(ref(was), 'left', ref(to)); stead.in_onexit_call = false res = par('^^',res,v); self.where = deref(to) stead.in_entered_call = true - v = call(ref(to), 'entered', deref(was)); + v = call(ref(to), 'entered', ref(was)); stead.in_entered_call = false res = par('^^',res,v); end diff --git a/stead/input.lua b/stead/input.lua index 0bc3e9a..9cf4713 100644 --- a/stead/input.lua +++ b/stead/input.lua @@ -199,7 +199,7 @@ game.action = stead.hook(game.action, function (f, s, cmd, ...) if game.inp_enter then return call(here(), 'inp_enter'); end - return nil, true -- nothing todo + return nil -- nothing todo end return f(s, cmd, unpack(arg)) end) @@ -242,12 +242,12 @@ input_kbd = function(s, down, key) else input._txt = input._txt:sub(1, input._txt:len() - 1); end - return "look" + return "wait" end local c = kbdxlat(key); if not c then return end input._txt = input._txt..c; - return "look" + return "wait" end end @@ -266,8 +266,11 @@ function input_esc(s) return s:gsub("\\","\\\\"):gsub(">","\\>"):gsub("[^ ]+", rep):gsub("[ \t]", rep); end -function inp(info, txt) - local v = { nam = '', _txt = '', info = info } +function inp(n, info, txt) + if type(n) ~= 'string' or type(info) ~= 'string' then + error ("Wrong parameter to inp.", 2); + end + local v = { nam = n, _txt = '', info = info } if txt then v._txt = txt end @@ -299,5 +302,12 @@ function inp(info, txt) end return true end + v.save = function(self, name, h, need) + if need then + h:write(stead.string.format("%s = inp (%q, %q, %q);\n", + name, self.nam, self.info, self._txt)) + end + savemembers(h, self, name, false); + end return obj(v) end diff --git a/stead/object.lua b/stead/object.lua index 95c8796..50c4e2f 100644 --- a/stead/object.lua +++ b/stead/object.lua @@ -1,40 +1,50 @@ -obj = stead.inherit(obj, function(v) - if v.use then - v.use = stead.hook(v.use, function(f, s, on, ...) - return f(s, ref(on), unpack(arg)) - end) - end - if v.used then - v.used = stead.hook(v.used, function(f, s, by, ...) - return f(s, ref(by), unpack(arg)) - end) - end - return v -end) +function player_use(self, what, onwhat, ...) + local obj, obj2, v, vv, r; + local scene_use_mode = false -room = stead.inherit(room, function(v) - if v.enter then - v.enter = stead.hook(v.enter, function(f, s, from, ...) - return f(s, ref(from), unpack(arg)) - end) + obj = self:srch(what); -- in inv? + if not obj then -- no + obj = ref(self.where):srch(what); -- in scene? + if not obj then -- no! + return game.err, false; + end + scene_use_mode = true -- scene_use_mode! end - if v.entered then - v.entered = stead.hook(v.entered, function(f, s, from, ...) - return f(s, ref(from), unpack(arg)) - end) + if onwhat == nil then -- only one? + if scene_use_mode then + return self:action(what, unpack(arg)); -- call act + else + v, r = call(ref(obj),'inv', unpack(arg)); -- call inv + end + if not v and r ~= true then + v, r = call(game, 'inv', obj, unpack(arg)); + end + return v, r; end - if v.exit then - v.exit = stead.hook(v.exit, function(f, s, to, ...) - return f(s, ref(to), unpack(arg)) - end) + obj2 = ref(self.where):srch(onwhat); -- in scene? + if not obj2 then + obj2 = self:srch(onwhat); -- in inv? end - if v.left then - v.left = stead.hook(v.left, function(f, s, to, ...) - return f(s, ref(to), unpack(arg)) - end) + if not obj2 or obj2 == obj then + return game.err, false; end - return v -end) + + obj = ref(obj) + obj2 = ref(obj2) + + if not scene_use_mode or isSceneUse(obj) then + v, r = call(obj, 'use', obj2, unpack(arg)); + if r ~= false then + vv = call(obj2, 'used', obj, unpack(arg)); + end + end + if not v and not vv then + v, r = call(game, 'use', obj, obj2, unpack(arg)); + end + return stead.par(' ', v, vv); +end + +pl.use = player_use; function vobj_save(self, name, h, need) local w diff --git a/stead/stead.lua b/stead/stead.lua index 722e3d8..23341e9 100644 --- a/stead/stead.lua +++ b/stead/stead.lua @@ -85,6 +85,7 @@ end function pclr() cctx().txt = nil end +stead.pclr = pclr function pget() return cctx().txt; @@ -1020,7 +1021,7 @@ function player_action(self, what, ...) if not obj then return call(ref(game), 'action', what, unpack(arg)); --player_do(self, what, unpack(arg)); end - v, r = player_take(self, what); + v, r = player_take(self, what, unpack(arg)); if not v then v, r = call(ref(obj), 'act', unpack(arg)); if not v and r ~= true then @@ -1030,20 +1031,20 @@ function player_action(self, what, ...) return v, r; end -function player_take(self, what) +function player_take(self, what, ...) local v,r,obj,w obj,w = ref(self.where):srch(what); if not obj then return nil, false; end - v,r = call(ref(obj), 'tak'); + v,r = call(ref(obj), 'tak', unpack(arg)); if v and r ~= false then take(obj, w); end return v; end -function player_use(self, what, onwhat) +function player_use(self, what, onwhat, ...) local obj, obj2, v, vv, r; local scene_use_mode = false @@ -1057,12 +1058,12 @@ function player_use(self, what, onwhat) end if onwhat == nil then -- only one? if scene_use_mode then - return self:action(what); -- call act + return self:action(what, unpack(arg)); -- call act else - v, r = call(ref(obj),'inv'); -- call inv + v, r = call(ref(obj),'inv', unpack(arg)); -- call inv end if not v and r ~= true then - v, r = call(game, 'inv', obj); + v, r = call(game, 'inv', obj, unpack(arg)); end return v, r; end @@ -1074,13 +1075,13 @@ function player_use(self, what, onwhat) return game.err, false; end if not scene_use_mode or isSceneUse(ref(obj)) then - v, r = call(ref(obj), 'use', obj2); + v, r = call(ref(obj), 'use', obj2, unpack(arg)); if r ~= false then - vv = call(ref(obj2), 'used', obj); + vv = call(ref(obj2), 'used', obj, unpack(arg)); end end if not v and not vv then - v, r = call(game, 'use', obj, obj2); + v, r = call(game, 'use', obj, obj2, unpack(arg)); end return stead.par(' ', v, vv); end @@ -1417,10 +1418,10 @@ function for_each(o, n, f, fv, ...) end end +function isCode(s) + return type(s) == 'function' and type(stead.functions[s]) == 'table' +end function for_each_codeblock(f,...) - local function isCode(s) - return type(s) == 'function' and type(stead.functions[s]) == 'table' - end for_each(_G, '_G', f, isCode, unpack(arg)) end @@ -1473,7 +1474,7 @@ function savevar (h, v, n, need) local r,f if v == nil or type(v) == "userdata" or type(v) == "function" then - if type(v) == "function" and stead.functions[v] and need then + if isCode(v) and need then if type(stead.functions[v].key_name) == 'string' and stead.functions[v].key_name ~= n then h:write(stead.string.format("%s=%s\n", n, stead.functions[v].key_name)) @@ -1609,6 +1610,7 @@ Commands:^ back, inv, way, obj, quit, save , load .]], pl ='pl', showlast = true, + version = "1.1.6", -- last version before 1.2.0 }; function strip(s) local s = tostring(s); @@ -1722,7 +1724,6 @@ iface = { if cmd == '' then cmd = 'look' end -- me():tag(); local oldloc = here(); - if cmd == 'look' then stead.state = true r,v = me():look(); @@ -1754,6 +1755,10 @@ iface = { if v ~= false and game.showlast then return r; end + elseif cmd == 'wait' then + v = nil; + r = nil; + stead.state = true elseif cmd == 'nop' then v = true; r = nil; @@ -2373,9 +2378,6 @@ function isForSave(k, v, s) -- k - key, v - value, s -- parent table if type(v) == 'function' or type(v) == 'userdata' then return false end - if game.version and game.version >= "1.2.0" then - return stead.string.find(k, '_') == 1 - end return stead.string.find(k, '_') == 1 or stead.string.match(k,'^%u') end diff --git a/stead/vars.lua b/stead/vars.lua index 46e4086..bc69c04 100644 --- a/stead/vars.lua +++ b/stead/vars.lua @@ -1,5 +1,4 @@ -isForSave = stead.hook(isForSave, -function (f, k, v, s, ...) -- k - key, v - value, s -- parent table +function isForSave(k, v, s) -- k - key, v - value, s -- parent table local i,o if type(s.var) == 'table' then for i,o in ipairs(s.var) do @@ -8,8 +7,14 @@ function (f, k, v, s, ...) -- k - key, v - value, s -- parent table end end end - return f(k, v, s, unpack(arg)) -end) + if type(k) == 'function' then + return false + end + if type(v) == 'function' or type(v) == 'userdata' then + return false + end + return stead.string.find(k, '_') == 1 +end function __vars_fill(v) local k,o diff --git a/stead/xobj.lua b/stead/xobj.lua index fd1827d..790124c 100644 --- a/stead/xobj.lua +++ b/stead/xobj.lua @@ -1,64 +1,114 @@ -function xobj(v) -- object without name and dsc, but with xact attribute - if v.nam == nil then - v.nam = '' - end - if v.dsc == nil then - v.dsc = '' - end - v.xact = v.act - v.act = function(s) - local r,v = call(s, 'xact'); - if type(r) == 'string' then r = do_xact(r) end - return r,v - end - return obj(v) +function isXobject(s) + return type(s) == 'table' and s.xobject_type; end -xact = function(f) -- just simple action! +xobj = stead.hook(obj, function(f, v, ...) -- object without name and dsc, but with xact attribute + local hook_act = function(v, n) + local k,o + if type(v.var) == 'table' then + for k,o in ipairs(v.var) do -- var add + if o == n then + stead.table.insert(v.var, 'x'..n); + break + end + end + end + return function(s, ...) + local r, v = call(s, 'x'..n, unpack(arg)); + if type(r) == 'string' then + r = do_xact(s, r); + end + return r,v + end + end + v = f(v, unpack(arg)) + v.xdsc = v.dsc + v.dsc = hook_act(v, 'dsc'); + v.xact = v.act + v.act = hook_act(v, 'act'); + v.xinv = v.inv + v.inv = hook_act(v, 'inv'); + v.xtak = v.tak + v.tak = hook_act(v, 'tak'); + v.xuse = v.use + v.use = hook_act(v, 'use'); + v.xused = v.used + v.used = hook_act(v, 'used'); + v.xobject_type = true + return v +end) + +xact = function(n, f) -- just simple action! local v = {}; + if type(n) ~= 'string' or (type(f) ~= 'string' and not isCode(f)) then + error ("Wrong parameter to xact.", 2) + end + v.nam = n + v.act = f; v = xobj(v); - v.xact = f; + v.save = function(self, name, h, need) + if need then + local f = self.xact; + if isCode(f) then + f = stead.string.format("code %q", stead.functions[f].code); + else + f = stead.string.format("%q", f); + end + h:write(stead.string.format("%s = xact(%q, %s);\n", name, self.nam, f)) + end + savemembers(h, self, name, false); + end return v end -do_xact = function(str) +do_xact = function(self, str) + local aarg = {} + local function parg(v) + stead.table.insert(aarg, v); + return '' + end local xrefrep = function(str) local s = stead.string.gsub(str,'[{}]',''); - local o = stead.string.gsub(s,'^(.*):.*$','%1'); - local d = stead.string.gsub(s,'^.*:(.*)$','%1'); - return xref(d, ref(o)); + local o,d, a; + local i = s:find(":", 1, true); + aarg = {} + if i then + o = s:sub(1, i - 1); + d = s:sub(i + 1); + i = o:find("(", 1, true); + if i then + a = o:sub(i); + o = o:sub(1, i - 1); + a:gsub('[^,()]+', parg); + end + if o == '' then o = self end + else + o = self + d = s; + end + local oo = ref(o) + if not oo then + oo = objs():srch(o) + end + return xref(d, ref(oo), unpack(aarg)); end if type(str) ~= 'string' then return end local s = stead.string.gsub(str,'{[^}]+}', xrefrep); return s; end -xdsc = function(v) - v.nam = '' - v.xdsc = v.dsc - v.dsc = function(s) - local str = call(s, 'xdsc'); - if type(str) == 'string' then - return do_xact(str); - end - return str - end - return obj(v) -end - xdsc_obj = obj { nam = '', dsc = function(s) local str = call(here(), 'xdsc'); if type(str) == 'string' then - return do_xact(str); + return do_xact(s, str); end return str end, } -function xroom(v) - v = room(v) +xroom = stead.inherit(room, function(v) v.obj:add('xdsc_obj', 1); -- first object is always meta-descriptor return v; -end +end)