From 93161c64659e4db3fc87d8e7c51d349ea32ffc52 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Wed, 14 Feb 2024 15:55:00 -0800 Subject: [PATCH] Stacked moves --- board.lua | 12 ++++-- checkpoint.lua | 2 +- cursor.lua | 94 +++++++++++++++++++++++++++++++-------------- state_gameround.lua | 25 +++++++++--- state_wonround.lua | 17 ++++---- watcher.lua | 4 ++ 6 files changed, 109 insertions(+), 45 deletions(-) diff --git a/board.lua b/board.lua index 2d3c4d2..8dfa696 100644 --- a/board.lua +++ b/board.lua @@ -129,6 +129,7 @@ function board:find_automove() 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.cursor:drop_grab_silent() self:animate_and_move_to_well(s,w) self.last_card=top @@ -174,13 +175,16 @@ function board:draw() end end + local grabs={} + for s_ix in all(self.cursor.grabbed_slots) do + grabs[s_ix]=(grabs[s_ix] or 0)+1 + end local function forall_slots(cb) for s_ix=1,#self.slots do local s=self.slots[s_ix] local l=self.ruleset.layouts:slot(s_ix) - local n=#s.contents - if (self.cursor.grabbed==s_ix) n-=1 + local n=#s.contents-(grabs[s_ix] or 0) cb(x,y,s_ix,s,l,n) end @@ -233,8 +237,8 @@ end function slot:add(card) add(self.contents,card) end -function slot:peek() - return self.contents[#self.contents] +function slot:peek(depth) + return self.contents[#self.contents-(depth or 0)] end function slot:pop() return deli(self.contents,#self.contents) diff --git a/checkpoint.lua b/checkpoint.lua index e503ddb..c7eaef1 100644 --- a/checkpoint.lua +++ b/checkpoint.lua @@ -36,5 +36,5 @@ function checkpoint:apply(board) add(board.wells[w].contents,i) end end - board.cursor.grabbed=nil + board.cursor:drop_grab() end \ No newline at end of file diff --git a/cursor.lua b/cursor.lua index a806c12..d9a3980 100644 --- a/cursor.lua +++ b/cursor.lua @@ -11,16 +11,17 @@ function cursor:init(board) self.hover_x=self.ruleset.n_slots\2 self.hover_y=1 self.saved_hover_x_y=nil - self.grabbed=nil + self.grabbed_slots={} end function cursor:acceptance_state() local hover=self:hover_slot() - if self.grabbed then - if hover==self.grabbed then + local slot=self:grabbed_slot() + if slot then + if hover==slot then return acceptance_state.no_move end - local source=self.board.slots[self.grabbed] + local source=self.board.slots[slot] local target=self.board.slots[self:hover_slot()] local card=source:peek() if target:would_accept(card) then @@ -38,13 +39,16 @@ function cursor:save_hover() self.saved_hover_x_y={self.hover_x,self.hover_y} end +--[[ function cursor:restore_hover() self.wants_to_restore_hover=true end +]] +--[[ function cursor:actually_restore_hover() if (not self.saved_hover_x_y) return - self.wants_to_restore_hover=false + -- self.wants_to_restore_hover=false -- try restoring hover x local old_hover_x,old_hover_y=self.hover_x,self.hover_y @@ -62,23 +66,27 @@ function cursor:actually_restore_hover() i() end end +]]-- function cursor:toggle_grab() local acc,src,tar=self:acceptance_state() local slot=self:hover_slot() if acc==acceptance_state.not_grabbed then if (not self.board.watcher:intercept("grab",slot)) sounds:dire() return - if (self.board.slots[slot]:peek()) self.grabbed=slot + if (self.board.slots[slot]:peek()) self.grabbed_slots={slot} self:save_hover() sounds:menu() elseif acc==acceptance_state.would_accept then if (not self.board.watcher:intercept("drop",slot)) sounds:dire() return self.board:pre_move(src:peek()) - local card=src:pop() - tar:add(card) - self.grabbed=nil - self.board:on_move(card) - self:restore_hover() + while self:acceptance_state() == acceptance_state.would_accept do + local card=src:pop() + tar:add(card) + deli(self.grabbed_slots) + end + self.grabbed_slots={} + self.board:on_move() + -- if (#self.grabbed_slots == 0) self:restore_hover() sounds:menu() elseif acc==acceptance_state.no_move or acc==acceptance_state.would_not_accept then self:drop_grab() @@ -87,15 +95,30 @@ function cursor:toggle_grab() end end +function cursor:incr_grab() + local slot=self:hover_slot() + if (slot!=self:grabbed_slot()) return + if (not self.board.watcher:intercept("incr_grab",slot)) sounds:dire() return + local new_card = self.board.slots[slot]:peek(#self.grabbed_slots) + if (not new_card) return + local old_card = self.board.slots[slot]:peek(#self.grabbed_slots-1) + if (not self:_can_incr_grab(old_card,new_card)) return + add(self.grabbed_slots,slot) + sounds:menu() +end + +function cursor:drop_grab_silent() + self.grabbed_slots={} +end function cursor:drop_grab() if (not self.board.watcher:intercept("cancel")) sounds:dire() return - self.grabbed=nil - self:restore_hover() + self.grabbed_slots={} + -- self:restore_hover() sounds:menu() end function cursor:update() - if (self.wants_to_restore_hover) self:actually_restore_hover() + -- if (self.wants_to_restore_hover) self:actually_restore_hover() end function cursor:move_x(dx) @@ -114,7 +137,7 @@ end function cursor:move_y(dy) local old_y=self.hover_y if (self.hover_y==0 and dy==1) self.hover_y=1 - if (self.hover_y==1 and dy==-1) self.hover_y=0 + if (self.hover_y==1 and dy==-1 and #self.grabbed_slots<2) self.hover_y=0 if (self:acceptance_state()==acceptance_state.would_not_accept) if (not self:move_x(-1)) self.hover_y=old_y end @@ -123,27 +146,42 @@ function cursor:hover_slot() return self.hover_x+1 end +function cursor:grabbed_slot() + return self.grabbed_slots[#self.grabbed_slots] +end function cursor:grabbed_card() - if self.grabbed then - local slot=self.board.slots[self.grabbed] - return slot:peek() + local grabbed_slot=self:grabbed_slot() + if grabbed_slot then + return self.board.slots[grabbed_slot]:peek() end - return nil end function cursor:draw_at(l,i) - local card=self:grabbed_card() - local acc=self:acceptance_state() + local slot=self:grabbed_slot() - if card then - i+=1 - local x,y=l:place_card(i) - local card_fg=self.ruleset.deck:draw_card(x,y,card,{rotate=l.rotated}) - local fg=card_fg - draw_layout_hint(l,i,9,false) - else + if not slot then local filled=false if (i<1) i=1 filled=true draw_layout_hint(l,i,12,filled) + return end + + local not_moving=self:acceptance_state()==acceptance_state.no_move + for i2=1,#self.grabbed_slots do + local ix=i2-1 + if (not_moving) ix=#self.grabbed_slots-i2 + local card=self.board.slots[slot]:peek(ix) + + local x,y=l:place_card(i+i2) + local card_fg=self.ruleset.deck:draw_card(x,y,card,{rotate=l.rotated}) + local fg=card_fg + if (i2==1) draw_layout_hint(l,i+i2,9,false) + end +end + +function cursor:_can_incr_grab(c0,c1) + c0=self.board.ruleset.deck.cards[c0] + c1=self.board.ruleset.deck.cards[c1] + if (c0.suit!=c1.suit) return false + return c0.rank==c1.rank+1 or c1.rank==c0.rank+1 end \ No newline at end of file diff --git a/state_gameround.lua b/state_gameround.lua index 9eb67ea..5a3291c 100644 --- a/state_gameround.lua +++ b/state_gameround.lua @@ -2,7 +2,9 @@ state_gameround=klass() function state_gameround:init(watcher,ruleset) self.board=board:new(watcher,ruleset) self.outcome=nil + self.grab_frames=0 self.restart_frames=0 + self.picking_up=false end function state_gameround:enter() self:add_menu() end function state_gameround:exit() self:remove_menu() end @@ -22,6 +24,11 @@ end function state_gameround:update() self.board:update() + if btn(4) then + self.grab_frames+=1 + else + self.grab_frames=0 + end if btn(5) then self.restart_frames+=1 else @@ -38,16 +45,24 @@ function state_gameround:update() end if self.board:can_take_input() then - if (btnp(0)) self.board.cursor:move_x(-1) - if (btnp(1)) self.board.cursor:move_x(1) - if (btnp(2)) self.board.cursor:move_y(-1) - if (btnp(3)) self.board.cursor:move_y(1) - if (btnp(4)) self.board.cursor:toggle_grab() + if (btnp(0)) self.board.cursor:move_x(-1) self.picking_up=false + if (btnp(1)) self.board.cursor:move_x(1) self.picking_up=false + if (btnp(2)) self.board.cursor:move_y(-1) self.picking_up=false + if (btnp(3)) self.board.cursor:move_y(1) self.picking_up=false + if btnp(4) then + if self.grab_frames<4 then + self.board.cursor:toggle_grab() + self.picking_up=true + else + self.board.cursor:incr_grab() + end + end if btnp(5) and self.restart_frames < 4 then if self.board.cursor:grabbed_card() then self.board.cursor:drop_grab() else self.board:undo() + self.picking_up=false end end end diff --git a/state_wonround.lua b/state_wonround.lua index e2aa494..c17c390 100644 --- a/state_wonround.lua +++ b/state_wonround.lua @@ -12,8 +12,7 @@ function state_wonround:enter() sounds:win() completion_tracker:mark_seen(self.verse_id) completion_tracker:advance_completion_level(self.board:get_completion_level()) - self.has_tip = not seen_tip_this_session - seen_tip_this_session=true + if (self.board.watcher:allow_tips()) self.tip=deli(_won_round_tips,1) end function state_wonround:exit(new_top) end @@ -65,9 +64,13 @@ function state_wonround:draw() print("next",57,y+2,15) print("(🅾️)",57,y+8,15) - if self.has_tip then - local tip="tip: hold ❎ to restart" - local w=measure_text(tip) - print(tip,64-w\2,122,15) + if self.tip then + local w=measure_text(self.tip) + print(self.tip,64-w\2,122,15) end -end \ No newline at end of file +end + +_won_round_tips={ + "tip: hold ❎ to restart", + "tip: hold 🅾️ to stack cards" +} \ No newline at end of file diff --git a/watcher.lua b/watcher.lua index 72ee2f8..f3a8d45 100644 --- a/watcher.lua +++ b/watcher.lua @@ -3,6 +3,10 @@ function watcher:init(ruleset,seed,stages) self.ruleset=ruleset self.seed=seed self._stages=stages or {} + self._allow_tips=#self._stages == 0 +end +function watcher:allow_tips() + return self._allow_tips end function watcher:active_stage(board) local stage=self._stages[1]