hagen/gui.lua

330 lines
5.9 KiB
Lua

require "iuplua"
-- Hagen game engine
-- (c) Severák 2019
-- 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 = {}
issued_command = {}
-- API
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
room_ord[#room_ord+1] = def
return def
end
function item(def)
def.is_item = true
item_ord[#item_ord+1] = def
return def
end
function cls()
text.value = ""
end
function p(par)
if text.value=="" then
text.value = par
else
text.value = text.value .. "\n" .. par
end
text.scrollto = text.linecount .. ","
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
function has(what)
return game[what].w=="me"
end
function location_of(what)
return game[what].w
end
function is_here(what)
return game[what].w==game.me.w
end
-- end of API
-- 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 show_verbs()
paramsNo = 0
currVerb = ""
params = {}
local here = game[game.me.w]
commands[1]=nil
menu2codes={}
for i,verb in ipairs(verb_ord) do
if verb.always or here[verb.ref] or _has_subj_of(verb) then
local idx=commands.count+1
commands[idx] = verb.n
menu2codes[idx] = verb.ref
end
end
end
function show_items()
local verb = game[currVerb]
local parCode = verb.params[#params+1]
-- print("parCode="..parCode)
commands[1]=nil
menu2codes={}
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
local idx=commands.count+1
commands[idx] = item.n
menu2codes[idx] = item.ref
end
end
if commands.count=="0" then
show_verbs() -- situace kdy není možné zobrazit další krok v menu
-- TODO - vyřešit nějak líp
end
end
function process_param(param)
if paramsNo == 0 then
currVerb = param
paramsNo = #game[currVerb].params
else
params[#params+1]=param
end
-- debug:
--[[
print("param="..param)
print("params="..table.concat(params," "))
print("currVerb="..currVerb)
print("paramsNo="..paramsNo)
print("#params="..#params)
print "---"
]]
if #params==paramsNo then
p ""
p("> " .. table.concat(issued_command, " "))
issued_command = {}
game[currVerb].act(table.unpack(params))
if game.round then
game.round()
end
show_verbs()
else
show_items()
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.",
ref = "intro"
},
void = room{
n="void",
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.",
ref = "void"
},
vars = {}
}
-- utils
function read_config(filename)
filename = filename or ''
assert(type(filename) == 'string')
local ans,u,k,v,temp = {}, '_'
local f = io.open(filename)
if f then
f:close()
for line in io.lines(filename) do
temp = line:match('^%[(.+)%]$')
if temp ~= nil and u ~= temp then u = temp end
k,v = line:match('^([^=]+)=(.+)$')
if u ~= nil then
ans[u] = ans[u] or {}
if k ~= nil then
ans[u][k] = v
end
end
end
return ans
else
return {}
end
end
-- GUI
iup.SetGlobal("UTF8MODE","YES")
text = iup.multiline{expand="YES", readonly="YES", wordwrap="YES"}
commands = iup.list{expand="YES"}
function commands:action(text, i, selected)
if selected==1 then
-- print(text, i)
issued_command[#issued_command+1] = text
process_param(menu2codes[i])
-- print(menu2codes[i])
end
end
-- TODO - ovladání pomoci klávesnice
function commands:k_any(k)
if k==iup.K_UP or k==iup.K_DOWN then
-- print "<>"
end
if k==iup.K_CR then
-- print "Enter!"
end
end
local theme = read_config "theme.ini"
if theme._theme then
theme = theme._ -- hack - TODO - odstranit
end
setmetatable(theme, {__index = {
font = "Verdana, 12",
fgcolor = "#00000",
bgcolor = "#ffffff",
}})
vbox= iup.hbox{text, commands; expand=1}
window = iup.dialog{vbox, title = "Hagen", gap = "10", rastersize="640x480", font=theme.font, fgcolor=theme.fgcolor, bgcolor=theme.bgcolor}
-- iup.SetFocus(commands)
local gamefile
if arg[1] then
gamefile = arg[1]
else
gamefile = "syrecky.lua"
--[[
local hry = {"syrecky.lua"}
local hra = iup.Alarm("Hagen engine", "vyberte hru:", "Syrečky")
if hry[hra] then
gamefile = hry[hra]
else
os.exit(1)
end
]]
end
window:show()
-- loads game
load_game, err = loadfile(gamefile, "t", setmetatable(game, {__index=_G}))
if err then
print(err)
os.exit(1)
end
load_game()
local refcnt = 0
-- 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
refcnt = refcnt + 1
end
end
-- stupid cyber arm glitching again!
for i,obj in ipairs(verb_ord) do
print("verb " .. obj.ref)
end
for i,obj in ipairs(room_ord) do
print("room " .. obj.ref)
end
for i,obj in ipairs(item_ord) do
print("item " .. obj.ref)
end
print("refcnt = " .. refcnt)
print("#verb_ord = " .. #verb_ord)
print("#room_ord = " .. #room_ord)
print("#item_ord = " .. #item_ord)
print("#sum_ord = " .. #verb_ord + #room_ord + #item_ord)
window.title = game.title
walk("intro")
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
end