diff --git a/board.lua b/board.lua index 94e13c7..21392c6 100644 --- a/board.lua +++ b/board.lua @@ -39,16 +39,31 @@ function board:init(w) if (not lst) return new.rank==0 return new.rank==lst.rank+1 end)) + self.wells[#self.wells].obscured_by_last_well=true -- n_suits+2: arcana descending add(self.wells,well:new(self.ruleset,function(lst,new) if (new.suit!='a') return if (not lst) return new.rank==self.ruleset.n_arcana-1 return new.rank==lst.rank-1 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)) 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) local deal=deal(self.ruleset,seed) local n_usable_slots=self.ruleset.n_slots - 1 @@ -107,11 +122,12 @@ function board:find_automove() for s=1,#self.slots do local top=self.slots[s]:peek() 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 -- the top wells are blocked elseif self.wells[w]:would_accept(top) then self:animate_and_move_to_well(s,w) + self.last_card=top return true end @@ -135,18 +151,22 @@ end function board:draw() 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 local w=self.wells[w_ix] local l=self.ruleset.layouts:well(w_ix) 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 shadowed=true end for i=1,#w.contents do 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 @@ -235,4 +255,7 @@ function well:add(card) end function well:clear() self.contents={} +end +function well:peek() + return self.contents[#self.contents] end \ No newline at end of file diff --git a/engine.lua b/engine.lua index 28c9405..590002a 100644 --- a/engine.lua +++ b/engine.lua @@ -65,10 +65,10 @@ function lerp(x,x0,x1) return x0+x*(x1-x0) end -function csv(s) +function gsv(s) local ret=split(s,"\n") 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 end diff --git a/liturgy.lua b/liturgy.lua new file mode 100644 index 0000000..4e79ca4 --- /dev/null +++ b/liturgy.lua @@ -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 \ No newline at end of file diff --git a/main.p8 b/main.p8 index e7db3cc..3777237 100644 --- a/main.p8 +++ b/main.p8 @@ -13,6 +13,7 @@ __lua__ #include cursor.lua #include layout.lua #include layout_hint.lua +#include liturgy.lua #include ruleset.lua #include palette.lua #include progression.lua @@ -23,6 +24,7 @@ __lua__ #include state_gameround.lua #include state_ironman.lua #include state_restartmenu.lua +#include state_wonround.lua #include tutorial.lua #include text.lua #include watcher.lua diff --git a/progression.lua b/progression.lua index b0c9587..69eb6dd 100644 --- a/progression.lua +++ b/progression.lua @@ -1,8 +1,8 @@ progression={ -- 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 - 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 ruleset:new(3,7,2,9,8), -- by test: always winnable -- level 4 (first challenging) diff --git a/ruleset.lua b/ruleset.lua index 7f81689..bcf311e 100644 --- a/ruleset.lua +++ b/ruleset.lua @@ -18,7 +18,8 @@ function ruleset:init( -- Number of arcana (unbounded) -- For Fortune's Foundation: 22 n_arcana, - pool + pool, + preferred_verse ) self.completion_level=completion_level self.n_slots=n_slots @@ -26,6 +27,7 @@ function ruleset:init( self.n_cards_per_suit=n_cards_per_suit self.n_arcana=n_arcana self.pool=pool + self.preferred_verse=preferred_verse assert(self.n_slots<=11) assert(self.n_suits<=5) assert(self.n_cards_per_suit<=13) @@ -176,6 +178,7 @@ function ruleset:generate_layouts() i-=ruleset.n_suits 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==3) return layout:new(x+5,y,layout_mode.rotated) assert(false,"unknown well") end diff --git a/state_gameround.lua b/state_gameround.lua index ef88438..53b2b8c 100644 --- a/state_gameround.lua +++ b/state_gameround.lua @@ -33,7 +33,7 @@ function state_gameround:update() if (btnp(4)) self.board.cursor:toggle_grab() if (btnp(5)) self.board:undo() 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 function state_gameround:draw() diff --git a/state_wonround.lua b/state_wonround.lua new file mode 100644 index 0000000..cb29fce --- /dev/null +++ b/state_wonround.lua @@ -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 \ No newline at end of file diff --git a/tutorial.lua b/tutorial.lua index 01ca919..d670f91 100644 --- a/tutorial.lua +++ b/tutorial.lua @@ -34,5 +34,5 @@ tutorial={ function() return watcher:new(progression[5]) end, function() return watcher:new(progression[6]) end, function() return watcher:new(progression[7]) end, - completion_stage=3 + completion_stage=99--3 }