acceptance_state={ not_grabbed=0, would_accept=1, would_not_accept=2, no_move=3 } cursor=klass() function cursor:init(board) self.ruleset=board.ruleset self.board=board self.hover_x=self.ruleset.n_slots\2 self.hover_y=1 self.grabbed=nil end function cursor:acceptance_state() if self.grabbed then local hover=self:hover_slot() if hover==self.grabbed then return acceptance_state.no_move end local source=self.board.slots[self.grabbed] local target=self.board.slots[self:hover_slot()] local card=source:peek() if target:would_accept(card) then return acceptance_state.would_accept,source,target else return acceptance_state.would_not_accept end else return acceptance_state.not_grabbed end end function cursor:toggle_grab() local acc,src,tar=self:acceptance_state() if acc==acceptance_state.not_grabbed then if (self.board.slots[self:hover_slot()]:peek()) self.grabbed=self:hover_slot() elseif acc==acceptance_state.would_accept then local card=src:pop() tar:add(card) self.grabbed=nil self.board:on_move(card) elseif acc==acceptance_state.no_move or acc==acceptance_state.would_not_accept then self.grabbed=nil else assert(false,"invalid acceptance state") end end function cursor:move_x(dx) if (self.hover_y==0) return self.hover_x+=dx self.hover_x%=self.ruleset.n_slots -- TODO: Don't hard-code end function cursor:move_y(dy) if (self.hover_y==0 and dy==1) self.hover_y=1 if (self.hover_y==1 and dy==-1) self.hover_y=0 end function cursor:hover_slot() if (self.hover_y==0) return self.ruleset.n_slots+1 return self.hover_x+1 end function cursor:grabbed_card() if self.grabbed then local slot=self.board.slots[self.grabbed] return slot:peek() end return nil end function cursor:draw_at(l,x,y) local card=self:grabbed_card() local acc=self:acceptance_state() if card and acc!=acceptance_state.would_accept and acc!=acceptance_state.no_move then x+=sin(time()/2)*2+0.5 y+=sin(time()/4)+0.5+1 end x=flr(x) y=flr(y) local function draw_surround_box(fg) if (not fg) return if l.rotated then rect(x-4,y+6,x+13,y+16,fg) else rect(x-1,y-1,x+9,y+16,fg) end end local function draw_overlapping_box(fg) if (l.obscured) draw_surround_box(fg) return if l.rotated then rectfill(x-3,y+7,x+12,y+15,fg) else rectfill(x,y,x+8,y+15,fg) end end if card then local card_fg=self.ruleset.deck:draw_card(x,y,card,{rotate=l.rotated}) local fg=card_fg if (acc==acceptance_state.would_accept) fg=9 draw_surround_box(fg) else draw_overlapping_box(9) end end