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()
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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>."
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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)
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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
|
2019-08-17 21:43:55 +00:00
|
|
|
|
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
|
2019-08-17 21:43:55 +00:00
|
|
|
|
|
|
|
|
|
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()
|