Add liturgy

This commit is contained in:
Pyrex 2024-02-11 13:44:45 -08:00
parent a06ea160b2
commit 1f8a937107
9 changed files with 178 additions and 9 deletions

View File

@ -39,16 +39,31 @@ function board:init(w)
if (not lst) return new.rank==0 if (not lst) return new.rank==0
return new.rank==lst.rank+1 return new.rank==lst.rank+1
end)) end))
self.wells[#self.wells].obscured_by_last_well=true
-- n_suits+2: arcana descending -- n_suits+2: arcana descending
add(self.wells,well:new(self.ruleset,function(lst,new) add(self.wells,well:new(self.ruleset,function(lst,new)
if (new.suit!='a') return if (new.suit!='a') return
if (not lst) return new.rank==self.ruleset.n_arcana-1 if (not lst) return new.rank==self.ruleset.n_arcana-1
return new.rank==lst.rank-1 return new.rank==lst.rank-1
end)) end))
self.wells[#self.wells].obscured_by_last_well=true
-- top arcana
add(self.wells,well:new(self.ruleset,function(lst,new)
local w1=self.wells[self.ruleset.n_suits+1]
local w2=self.wells[self.ruleset.n_suits+2]
if (#w1.contents + #w2.contents != self.ruleset.n_arcana-1) return
return new.suit=='a'
end))
self:deal(w.seed or seeds:choose(self.ruleset.pool)) self:deal(w.seed or seeds:choose(self.ruleset.pool))
end end
function board:get_endgame_card()
local last_arcana=self.wells[#self.wells]:peek()
if (last_arcana) return last_arcana
return self.last_card or 1
end
function board:deal(seed) function board:deal(seed)
local deal=deal(self.ruleset,seed) local deal=deal(self.ruleset,seed)
local n_usable_slots=self.ruleset.n_slots - 1 local n_usable_slots=self.ruleset.n_slots - 1
@ -107,11 +122,12 @@ function board:find_automove()
for s=1,#self.slots do for s=1,#self.slots do
local top=self.slots[s]:peek() local top=self.slots[s]:peek()
if top then if top then
for w=1,#self.wells do for w=#self.wells,1,-1 do
if w<=self.ruleset.n_suits and self.slots[self.ruleset.n_slots+1]:peek()!=nil then if w<=self.ruleset.n_suits and self.slots[self.ruleset.n_slots+1]:peek()!=nil then
-- the top wells are blocked -- the top wells are blocked
elseif self.wells[w]:would_accept(top) then elseif self.wells[w]:would_accept(top) then
self:animate_and_move_to_well(s,w) self:animate_and_move_to_well(s,w)
self.last_card=top
return true return true
end end
@ -135,18 +151,22 @@ end
function board:draw() function board:draw()
local extra_slot_full=self.slots[self.ruleset.n_slots+1]:peek()!=nil local extra_slot_full=self.slots[self.ruleset.n_slots+1]:peek()!=nil
local last_well_full=self.wells[#self.wells]:peek()!=nil
for w_ix=1,#self.wells do for w_ix=1,#self.wells do
local w=self.wells[w_ix] local w=self.wells[w_ix]
local l=self.ruleset.layouts:well(w_ix) local l=self.ruleset.layouts:well(w_ix)
local shadowed=nil local shadowed=nil
if w.obscured_by_last_well and last_well_full then
shadowed=true
end
if w.obscured_by_extra_slot and extra_slot_full then if w.obscured_by_extra_slot and extra_slot_full then
shadowed=true shadowed=true
end end
for i=1,#w.contents do for i=1,#w.contents do
local x,y=l:place_card(i) local x,y=l:place_card(i)
self.ruleset.deck:draw_card(x,y,w.contents[i],{shadowed=shadowed}) self.ruleset.deck:draw_card(x,y,w.contents[i],{rotate=l.rotated,shadowed=shadowed})
end end
end end
@ -235,4 +255,7 @@ function well:add(card)
end end
function well:clear() function well:clear()
self.contents={} self.contents={}
end
function well:peek()
return self.contents[#self.contents]
end end

View File

@ -65,10 +65,10 @@ function lerp(x,x0,x1)
return x0+x*(x1-x0) return x0+x*(x1-x0)
end end
function csv(s) function gsv(s)
local ret=split(s,"\n") local ret=split(s,"\n")
for i,v in ipairs(ret) do for i,v in ipairs(ret) do
ret[i] = type(v) == "string" and split(v) or {v} end ret[i] = type(v) == "string" and split(v,"`") or {v} end
return ret return ret
end end

80
liturgy.lua Normal file
View File

@ -0,0 +1,80 @@
liturgy={
holy_book=gsv[[
rood 1`1,2
rood 2`3,4,5,6
rood 3`7,8,9,10
]],
sacred_text_lines=gsv
[[1`come into this thicket.
1`i, o man, have a bright wreath.
1`my laurel is vibrant.
2`the hollow of a stone.
2`this, too, opens to the key.
2`the tone of music delights me.
2`the daisies.
3`whose angel is black like fish
3`is scarred like fish too.
3`i know the elk's bite.
4`a log does not eat.
4`nor does it suffer.
4`why write? why sing?
4`why answer for it?
5`a wolf that comes when called
5`is sheared of its fur.
5`distolerate sweet things.
6`they are a regiment.
6`gather them.
6`bury their warglaives.
6`burn their holy book.
6`plant them like seeds.
7`driftwood in a wash.
7`the water is speaking.
7`the bark is for beavers.
7`the twigs are for you.
8`the stormwater drowns an ox.
8`go up in the canopy.
8`fire arrows down
9`catching a leaf, ride it.
9`suture its veins.
9`scatter glass in the vineyard.
10`one day, the seas will boil.
10`no one will be born again.]]
}
function liturgy:init()
local verse_lines={}
for line in all(self.sacred_text_lines) do
local verse=tonum(line[1])
if (not verse_lines[verse]) verse_lines[verse]={}
add(verse_lines[verse], line[2])
end
local annotated_verses={}
for bookdata in all(self.holy_book) do
local name=bookdata[1]
local ix=1
for verse in all(split(bookdata[2])) do
local annotated_verse_name=name
local lines=verse_lines[verse]
annotated_verse_name..=":"..ix.."-"
ix+=#lines
annotated_verse_name..=ix
local annotated_verse=""
for l in all(lines) do
if (annotated_verse!="") annotated_verse..="\n"
annotated_verse..=l
end
annotated_verses[verse]={annotated_verse_name,annotated_verse}
end
end
self.annotated_verses=annotated_verses
end
liturgy:init()
function liturgy:suggest_verse(ruleset,card)
local meta=ruleset.deck.cards[card]
local i=2+meta.rank
if (meta.suit!="a") i=ruleset.preferred_verse or i
return unpack(liturgy.annotated_verses[i])
end

View File

@ -13,6 +13,7 @@ __lua__
#include cursor.lua #include cursor.lua
#include layout.lua #include layout.lua
#include layout_hint.lua #include layout_hint.lua
#include liturgy.lua
#include ruleset.lua #include ruleset.lua
#include palette.lua #include palette.lua
#include progression.lua #include progression.lua
@ -23,6 +24,7 @@ __lua__
#include state_gameround.lua #include state_gameround.lua
#include state_ironman.lua #include state_ironman.lua
#include state_restartmenu.lua #include state_restartmenu.lua
#include state_wonround.lua
#include tutorial.lua #include tutorial.lua
#include text.lua #include text.lua
#include watcher.lua #include watcher.lua

View File

@ -1,8 +1,8 @@
progression={ progression={
-- level 1 -- level 1
ruleset:new(1,5,1,9,0), -- by test: always winnable ruleset:new(1,5,1,9,0,nil,1), -- by test: always winnable
-- level 2 -- level 2
ruleset:new(2,5,2,9,0), -- by test: always winnable ruleset:new(2,5,2,9,0,nil,2), -- by test: always winnable
-- level 3 -- level 3
ruleset:new(3,7,2,9,8), -- by test: always winnable ruleset:new(3,7,2,9,8), -- by test: always winnable
-- level 4 (first challenging) -- level 4 (first challenging)

View File

@ -18,7 +18,8 @@ function ruleset:init(
-- Number of arcana (unbounded) -- Number of arcana (unbounded)
-- For Fortune's Foundation: 22 -- For Fortune's Foundation: 22
n_arcana, n_arcana,
pool pool,
preferred_verse
) )
self.completion_level=completion_level self.completion_level=completion_level
self.n_slots=n_slots self.n_slots=n_slots
@ -26,6 +27,7 @@ function ruleset:init(
self.n_cards_per_suit=n_cards_per_suit self.n_cards_per_suit=n_cards_per_suit
self.n_arcana=n_arcana self.n_arcana=n_arcana
self.pool=pool self.pool=pool
self.preferred_verse=preferred_verse
assert(self.n_slots<=11) assert(self.n_slots<=11)
assert(self.n_suits<=5) assert(self.n_suits<=5)
assert(self.n_cards_per_suit<=13) assert(self.n_cards_per_suit<=13)
@ -176,6 +178,7 @@ function ruleset:generate_layouts()
i-=ruleset.n_suits i-=ruleset.n_suits
if (i==1) return layout:new(x,y,layout_mode.obscured) if (i==1) return layout:new(x,y,layout_mode.obscured)
if (i==2) return layout:new(x+10,y,layout_mode.obscured) if (i==2) return layout:new(x+10,y,layout_mode.obscured)
if (i==3) return layout:new(x+5,y,layout_mode.rotated)
assert(false,"unknown well") assert(false,"unknown well")
end end

View File

@ -33,7 +33,7 @@ function state_gameround:update()
if (btnp(4)) self.board.cursor:toggle_grab() if (btnp(4)) self.board.cursor:toggle_grab()
if (btnp(5)) self.board:undo() if (btnp(5)) self.board:undo()
end end
if (self.board:is_won()) self.outcome="win" self.done=true if (self.board:is_won()) self.outcome="win" self.done=true main.state_manager:push(state_wonround:new(self.board))
end end
function state_gameround:draw() function state_gameround:draw()

61
state_wonround.lua Normal file
View File

@ -0,0 +1,61 @@
state_wonround=klass()
function state_wonround:init(board)
self.board=board
self.frame=0
self.frames=30
self.progress=0.0
self.card=self.board:get_endgame_card()
self.verse_name,self.verse=liturgy:suggest_verse(self.board.ruleset,self.card)
end
function state_wonround:enter() end
function state_wonround:exit(new_top) end
function state_wonround:reenter() end
function state_wonround:suspend() end
function state_wonround:update()
self.frame=min(self.frame+1,self.frames)
self.progress=self.frame/self.frames
self.board:set_restart_progress(self.progress)
if (self.progress<1.0) return
if (btnp(4)) self.done=true
end
function state_wonround:draw()
cls(13)
if self.progress<1.0 then
self.board:draw()
return
end
self.board.ruleset.deck:draw_card(0,0,self.card,{})
poke(0x5f54,0x60)
-- blow it up
sspr(0,0,9,16,55,28+sin(time())+0.5,18,32)
poke(0x5f54,0x00)
rectfill(0,0,8,15,13)
local w,_=measure_text(self.verse_name)
local x=64-w\2
-- rectfill(x,64,x+w-2,70,4)
print(self.verse_name,x,64,15)
line(x,70,x+w-2,70,15)
local oldx,oldw=x,w
local y=73
local w,h=measure_text(self.verse)
local x=64-w\2
rectfill(x-1,y-1,x+w,y+h-1,4)
print(self.verse,x,y,15)
--[[
for line in all(split(self.verse,"\n")) do
local w,_=measure_text(line)
print(line,64-w\2,y,7)
y+=6
end
]]--
y+=h+1
line(oldx,y,oldx+oldw-2,y,15)
print("next",56,y+2,15)
print("(🅾️)",56,y+8,15)
end

View File

@ -34,5 +34,5 @@ tutorial={
function() return watcher:new(progression[5]) end, function() return watcher:new(progression[5]) end,
function() return watcher:new(progression[6]) end, function() return watcher:new(progression[6]) end,
function() return watcher:new(progression[7]) end, function() return watcher:new(progression[7]) end,
completion_stage=3 completion_stage=99--3
} }