hagen/tui.lua

362 lines
7.8 KiB
Lua
Raw Normal View History

2019-08-16 22:46:02 +00:00
-- Hagen game engine
-- (c) Sever<65>k 2019
-- verze pro DOS
-- k<>d nedoporu<72>uju nikomu <20><>st, proto<74>e z<>rodek vzniknul b<>hem jednoho odpoledne
-- inspirace
-- - hra Gateway od Legend entrertaiment
-- - textovky od Petra Kaina
-- - textovkov<6F> 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
2019-08-17 21:25:45 +00:00
-- utils from lua wiki
2019-08-16 22:46:02 +00:00
-- 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
2019-08-17 21:25:45 +00:00
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
2019-08-16 22:46:02 +00:00
-- global functions
function cls()
2019-08-17 21:25:45 +00:00
os.execute "cls"
2019-08-16 22:46:02 +00:00
end
function p(par)
if par==nil then
return -- not write nil
end
2019-08-17 21:25:45 +00:00
print(reflow(par, 80)) -- reflowing to 80 cols limit
2019-08-16 22:46:02 +00:00
end
function here()
return game[game.me.w]
end
function move(what, where)
game[what].w = where
end
2019-08-17 21:25:45 +00:00
function walk(where, nocls)
2019-08-16 22:46:02 +00:00
assert(game[where], "room " .. where .. " does not exist")
move("me", where)
2019-08-17 21:25:45 +00:00
if not nocls then
cls()
end
2019-08-16 22:46:02 +00:00
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
2019-08-17 21:25:45 +00:00
function odmezeruj(n)
return string.gsub(n, " ", "-")
end
2019-08-16 22:46:02 +00:00
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
2019-08-17 21:25:45 +00:00
text2codes[odmezeruj(verb.n)] = verb.ref
2019-08-16 22:46:02 +00:00
end
end
end
function show_items()
local verb = game[currVerb]
for i,parCode in ipairs(verb.params) do
2019-08-17 21:25:45 +00:00
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
2019-08-16 22:46:02 +00:00
end
2019-08-17 21:25:45 +00:00
end
2019-08-16 22:46:02 +00:00
2019-08-17 21:25:45 +00:00
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
2019-08-16 22:46:02 +00:00
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."
},
2019-08-17 21:25:45 +00:00
void = room{
n="void",
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE."
},
2019-08-16 22:46:02 +00:00
vars = {}
}
-- speci<63>ln<6C> cli p<><70>kazy
game.refresh = verb{
n = "r",
always = true,
act = function()
walk(here().ref, true)
2019-08-16 22:46:02 +00:00
end
}
game.pomoc = verb{
n = "pomoc",
always = true,
act = function()
p "Hra se ovl<76>d<EFBFBD> kl<6B>vesnic<69>."
p "Pro p<>ehled slov, kter<65>m hra rozum<75> zadej p<>ikaz 'slova'."
2019-08-16 22:46:02 +00:00
p "P<EFBFBD><EFBFBD>kaz 'r' znova vyp<79><70>e m<>stnost, p<><70>kaz 'q' ukon<6F><6E> hru."
2019-08-17 21:25:45 +00:00
p "Slova nen<65> nutn<74> zad<61>vat cel<65>, nap<61>. 'pro tel' funguje stejn<6A> jako 'prozkoumej televizi'."
2019-08-16 22:46:02 +00:00
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<EFBFBD> slova:"
print(table.concat(slova, " "))
print "Napi<EFBFBD>te sloveso, jeho<68> parametry chcete vypsat: (Nic nic nevyp<79><70>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<EFBFBD> parametry p<><70>kazu:"
print(table.concat(slova, " "))
else
print "P<EFBFBD><EFBFBD>kaz nem<65> parametry."
end
show_verbs()
end
print ""
end
}
-- GUI loop
function gameloop()
while true do
io.stdout:write(">")
local inp = io.read()
2019-08-17 21:25:45 +00:00
if inp=="" and here().auto_command then
2019-08-16 22:46:02 +00:00
-- hack - auto pokra<72>ov<6F>n<EFBFBD>
2019-08-17 21:25:45 +00:00
inp = here().auto_command
print(">"..inp)
end
if inp == "?" then
inp = "pomoc"
2019-08-16 22:46:02 +00:00
end
if inp == "" then
-- continue
elseif inp == "q" or inp == "konec" or inp == "exit" then
return
else
show_verbs()
local words = explode(" ", inp)
2019-08-17 21:25:45 +00:00
local verb = guess_code(words[1])
if not verb then
print("Nerozum<EFBFBD>m slovesu '"..words[1].."'.")
2019-08-16 22:46:02 +00:00
else
local valid_input = true
2019-08-17 21:25:45 +00:00
currVerb = verb
2019-08-16 22:46:02 +00:00
show_items()
-- print("currVerb="..currVerb.."#")
params = {}
table.remove(words, 1)
if #game[currVerb].params > #words then
print "P<EFBFBD><EFBFBD>kaz z<>ejm<6A> nen<65> cel<65>."
2019-08-16 22:46:02 +00:00
end
for i,word in ipairs(words) do
2019-08-17 21:25:45 +00:00
-- TODO tady kontrolovat po<70>ad<61> p<><70>kaz<61>
local param = guess_code(word)
if not param then
print("Nerozum<EFBFBD>m slovu '" .. word .. "'.")
2019-08-16 22:46:02 +00:00
valid_input = false
else
2019-08-17 21:25:45 +00:00
params[#params+1] = param
2019-08-16 22:46:02 +00:00
end
end
if valid_input then
game[currVerb].act(table.unpack(params))
if game.round then
game.round()
end
print ""
2019-08-16 22:46:02 +00:00
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()