hagen/tui.lua

362 lines
7.8 KiB
Lua
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Hagen game engine
-- (c) Sever k 2019
-- verze pro DOS
-- k¢d nedoporuŸuju nikomu Ÿ¡st, proto§e z rodek vzniknul bØhem jednoho odpoledne
-- inspirace
-- - hra Gateway od Legend entrertaiment
-- - textovky od Petra Kaina
-- - textovkovì engine INSTEAD
-- globals
paramsNo = 0
params = {}
currVerb = nil
verb_ord = {}
room_ord = {}
item_ord = {}
menu2codes = {}
text2codes = {}
-- constructors
function verb(def)
def.is_verb = true
def.params = def.params or {}
verb_ord[#verb_ord+1] = def
return def
end
function room(def)
def.is_room = true
return def
end
function item(def)
def.is_item = true
item_ord[#item_ord+1] = def
return def
end
-- utils from lua wiki
-- explode(seperator, string)
function explode(d,p)
local t, ll
t={}
ll=0
if(#p == 1) then
return {p}
end
while true do
l = string.find(p, d, ll, true) -- find the next d in the string
if l ~= nil then -- if "not not" found then..
table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array.
ll = l + 1 -- save just after where we found it for searching next time.
else
table.insert(t, string.sub(p,ll)) -- Save what's left in our array.
break -- Break at end, as it should be, according to the lua manual.
end
end
return t
end
function wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 72
local here = 1-#indent1
local function check(sp, st, word, fi)
if fi - here > limit then
here = st - #indent
return "\n"..indent..word
end
end
return indent1..str:gsub("(%s+)()(%S+)()", check)
end
function reflow(str, limit, indent, indent1)
return (str:gsub("%s*\n%s+", "\n")
:gsub("%s%s+", " ")
:gsub("[^\n]+",
function(line)
return wrap(line, limit, indent, indent1)
end))
end
-- global functions
function cls()
os.execute "cls"
end
function p(par)
if par==nil then
return -- not write nil
end
print(reflow(par, 80)) -- reflowing to 80 cols limit
end
function here()
return game[game.me.w]
end
function move(what, where)
game[what].w = where
end
function walk(where, nocls)
assert(game[where], "room " .. where .. " does not exist")
move("me", where)
if not nocls then
cls()
end
p(game[where].n)
p(game[where].d)
for i,item in ipairs(item_ord) do
if item.d and item.w==here().ref then
p(item.d)
end
end
show_verbs()
end
-- TODO - checkovat vçechny parametry
function _has_subj_of(verb)
local parCode = verb.params[#params+1]
for i,item in ipairs(item_ord) do
if item[parCode] and (verb.global_reach or item.w==here().ref or item.w=="me") then
return true
end
end
return false
end
function odmezeruj(n)
return string.gsub(n, " ", "-")
end
function show_verbs()
paramsNo = 0
currVerb = ""
params = {}
text2codes = {}
local here = game[game.me.w]
menu2codes={}
for i,verb in ipairs(verb_ord) do
if verb.always or here[verb.ref] or _has_subj_of(verb) then
text2codes[odmezeruj(verb.n)] = verb.ref
end
end
end
function show_items()
local verb = game[currVerb]
for i,parCode in ipairs(verb.params) do
for i,item in ipairs(item_ord) do
if item[parCode] and (verb.global_reach or item.w==here().ref or item.w=="me") then
text2codes[odmezeruj(item.n)] = item.ref
end
end
end
end
function guess_code(prefix)
if text2codes[prefix] then
return text2codes[prefix]
end
local possible = {}
for word,code in pairs(text2codes) do
local at = string.find(word, prefix, 1, true)
if at==1 then
possible[#possible+1] = code
end
end
if #possible==1 then
return possible[1]
end
end
-- game defaults
game = {
title = "Emty game",
me = item{
w="intro"
},
intro = room{
n="void",
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE."
},
void = room{
n="void",
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE."
},
vars = {}
}
-- speci ln¡ cli pý¡kazy
game.refresh = verb{
n = "r",
always = true,
act = function()
walk(here().ref, true)
end
}
game.pomoc = verb{
n = "pomoc",
always = true,
act = function()
p "Hra se ovl d  kl vesnic¡."
p "Pro pýehled slov, kterìm hra rozum¡ zadej pýikaz 'slova'."
p "Pý¡kaz 'r' znova vyp¡çe m¡stnost, pý¡kaz 'q' ukonŸ¡ hru."
p "Slova nen¡ nutn zad vat cel , napý. 'pro tel' funguje stejnØ jako 'prozkoumej televizi'."
end
}
game.slova = verb{
n = "slova",
always = true,
act = function()
show_verbs()
local slova = {}
for text, code in pairs(text2codes) do
slova[#slova+1] = text
end
print "Platn  slova:"
print(table.concat(slova, " "))
print "Napiçte sloveso, jeho§ parametry chcete vypsat: (Nic nic nevyp¡çe.)"
local sloveso = io.read()
if sloveso ~= "" and text2codes[sloveso] then
currVerb = text2codes[sloveso]
text2codes = {}
show_items()
local slova = {}
for text, code in pairs(text2codes) do
slova[#slova+1] = text
end
if #slova>0 then
print "Platn parametry pý¡kazu:"
print(table.concat(slova, " "))
else
print "Pý¡kaz nem  parametry."
end
show_verbs()
end
print ""
end
}
-- GUI loop
function gameloop()
while true do
io.stdout:write(">")
local inp = io.read()
if inp=="" and here().auto_command then
-- hack - auto pokraŸov 
inp = here().auto_command
print(">"..inp)
end
if inp == "?" then
inp = "pomoc"
end
if inp == "" then
-- continue
elseif inp == "q" or inp == "konec" or inp == "exit" then
return
else
show_verbs()
local words = explode(" ", inp)
local verb = guess_code(words[1])
if not verb then
print("Nerozum¡m slovesu '"..words[1].."'.")
else
local valid_input = true
currVerb = verb
show_items()
-- print("currVerb="..currVerb.."#")
params = {}
table.remove(words, 1)
if #game[currVerb].params > #words then
print "Pý¡kaz zýejmØ nen¡ celì."
end
for i,word in ipairs(words) do
-- TODO tady kontrolovat poýad¡ pý¡kaz…
local param = guess_code(word)
if not param then
print("Nerozum¡m slovu '" .. word .. "'.")
valid_input = false
else
params[#params+1] = param
end
end
if valid_input then
game[currVerb].act(table.unpack(params))
if game.round then
game.round()
end
print ""
end
end
end
end
end
local gamefile
if arg[1] then
gamefile = arg[1]
else
gamefile = "syrecky.lua"
end
-- loads game
load_game, err = loadfile(gamefile, "t", setmetatable(game, {__index=_G}))
if err then
print(err)
os.exit(1)
end
load_game()
-- add refs
for ref,obj in pairs(game) do
if type(obj)=='table' and (obj.is_verb or obj.is_room or obj.is_item) then
obj.ref = ref
end
end
walk("intro")
gameloop()