mirror of
https://github.com/Oreolek/ink-instead.git
synced 2024-04-29 23:59:25 +03:00
185 lines
3.9 KiB
Lua
185 lines
3.9 KiB
Lua
local debug = function(x) print( require('test/luaunit').prettystr(x) ) end
|
|
|
|
local is = function (what, node)
|
|
return node ~= nil
|
|
and (type(node) == "table" and node[1] == what)
|
|
end
|
|
|
|
return function (tree)
|
|
local s = {
|
|
globalTags = {},
|
|
state = {
|
|
visitCount = {},
|
|
}
|
|
}
|
|
|
|
local pointer = 1
|
|
local knots = {}
|
|
local tags = {} -- maps (pointer to para) -> (list of tags)
|
|
local tagsForContentAtPath = {}
|
|
local currentChoicesPointers = {}
|
|
|
|
-- TODO state should contain tree/pointer to be able to save / load
|
|
|
|
local preProcess = function ()
|
|
|
|
local aboveTags = {}
|
|
local lastPara = {}
|
|
local lastKnotName
|
|
|
|
for p, n in ipairs(tree) do
|
|
if is('knot', n) then -- FIXME stitches
|
|
knots[n[2]] = p
|
|
--print(v[2],k)
|
|
end
|
|
|
|
if is('tag', n) then
|
|
if n[2] == 'global' then
|
|
table.insert(s.globalTags, n[3])
|
|
end
|
|
if n[2] == 'above' then
|
|
if lastKnotName then table.insert(tagsForContentAtPath[lastKnotName], n[3]) end
|
|
table.insert(aboveTags, n[3])
|
|
end
|
|
if n[2] == 'end' then
|
|
table.insert(tags[lastPara], n[3])
|
|
end
|
|
end
|
|
|
|
if is('knot', n) or is('stitch', n) then
|
|
lastKnotName = n[2]
|
|
tagsForContentAtPath[lastKnotName] = {}
|
|
end
|
|
|
|
if is('para', n) then
|
|
tags[p] = aboveTags
|
|
aboveTags = {}
|
|
lastPara = p
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local goToKnot = function(knotName)
|
|
if knots[knotName] then
|
|
s.state.visitCount[knotName] = s.state.visitCountAtPathString(knotName) + 1
|
|
pointer = knots[knotName] + 1 -- go to the line after the knot
|
|
else
|
|
print('unknown knot', knotName)
|
|
end
|
|
end
|
|
|
|
local isNext = function (what)
|
|
return is(what, tree[pointer])
|
|
end
|
|
|
|
local getPara = function ()
|
|
if isNext('para') then return tree[pointer][2] end
|
|
end
|
|
|
|
local update
|
|
update = function ()
|
|
|
|
if isNext('knot') then
|
|
-- FIXME: we shouldn't continue to next knot automatically probably - how about stitches?
|
|
--next = goToKnot(next[2])
|
|
end
|
|
|
|
if isNext('divert') then
|
|
goToKnot(tree[pointer][2])
|
|
update()
|
|
return
|
|
end
|
|
|
|
if isNext('tag') then
|
|
|
|
pointer = pointer + 1
|
|
update()
|
|
return
|
|
end
|
|
|
|
s.canContinue = isNext('para')
|
|
|
|
s.currentChoices = {}
|
|
currentChoicesPointers = {}
|
|
|
|
if isNext('option') then
|
|
local choiceDepth = tree[pointer][2]
|
|
-- find all choices on the same level in the same knot and in the same super-choice
|
|
for p=pointer, #tree do
|
|
local n = tree[p]
|
|
--print('looking for options', choiceDepth, n[1], n[2])
|
|
if is('knot', n) or is('stitch', n) or (is('option', n) and n[2] < choiceDepth) then
|
|
--print('stop looking for options');
|
|
break
|
|
end
|
|
|
|
if is('option', n) and n[2] == choiceDepth then
|
|
-- print('adding', p, n[3])
|
|
table.insert(currentChoicesPointers, p)
|
|
table.insert(s.currentChoices, {
|
|
text = (n[3] or '') .. (n[4] or ''),
|
|
choiceText = n[3] .. (n[5] or ''),
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local step = function ()
|
|
end
|
|
|
|
s.canContinue = nil
|
|
|
|
s.continue = function()
|
|
|
|
local res = getPara()
|
|
s.currentTags = tags[pointer] or {}
|
|
|
|
pointer = pointer + 1
|
|
update()
|
|
|
|
if isNext('glue') then
|
|
pointer = pointer + 1
|
|
update()
|
|
res = res .. s.continue()
|
|
end
|
|
|
|
return res;
|
|
end
|
|
|
|
s.currentChoices = {}
|
|
|
|
s.chooseChoiceIndex = function(index)
|
|
pointer = currentChoicesPointers[index]+1
|
|
update()
|
|
end
|
|
|
|
s.choosePathString = function(knotName)
|
|
goToKnot(knotName)
|
|
update()
|
|
end
|
|
|
|
s.state.visitCountAtPathString = function(knotName)
|
|
return s.state.visitCount[knotName] or 0
|
|
end
|
|
|
|
s.tagsForContentAtPath = function(knotName)
|
|
return tagsForContentAtPath[knotName] or {}
|
|
end
|
|
|
|
s.currentTags = {}
|
|
|
|
s.variablesState = {}
|
|
-- s.state.ToJson();s.state.LoadJson(savedJson);
|
|
|
|
preProcess()
|
|
--debug(tree)
|
|
--debug(tags)
|
|
|
|
-- debug
|
|
s._tree = tree
|
|
|
|
return s
|
|
end
|