187 lines
4.9 KiB
Lua
187 lines
4.9 KiB
Lua
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.saved_hover_x_y=nil
|
|
self.grabbed_slots={}
|
|
end
|
|
|
|
function cursor:acceptance_state()
|
|
local hover=self:hover_slot()
|
|
local slot=self:grabbed_slot()
|
|
if slot then
|
|
if hover==slot then
|
|
return acceptance_state.no_move
|
|
end
|
|
local source=self.board.slots[slot]
|
|
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
|
|
if (self.board.slots[hover]:peek()) return acceptance_state.not_grabbed
|
|
return acceptance_state.would_not_accept
|
|
end
|
|
end
|
|
|
|
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
|
|
|
|
-- try restoring hover x
|
|
local old_hover_x,old_hover_y=self.hover_x,self.hover_y
|
|
self.hover_x,self.hover_y=unpack(self.saved_hover_x_y)
|
|
|
|
-- try very hard to be in a valid spot
|
|
for i in all{
|
|
function() self.hover_x,self.hover_y=old_hover_x,old_hover_y end,
|
|
function() self:move_x(-1) end,
|
|
function() self:move_y(1) end,
|
|
function() self:move_x(-1) end,
|
|
function() self:move_y(-1) end
|
|
} do
|
|
if (self:acceptance_state()!=acceptance_state.would_not_accept) return
|
|
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_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())
|
|
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()
|
|
else
|
|
assert(false,"invalid acceptance state")
|
|
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_slots={}
|
|
-- self:restore_hover()
|
|
sounds:menu()
|
|
end
|
|
|
|
function cursor:update()
|
|
-- if (self.wants_to_restore_hover) self:actually_restore_hover()
|
|
end
|
|
|
|
function cursor:move_x(dx)
|
|
if (self.hover_y==0) return
|
|
if (dx==0) return
|
|
local orig_x=self.hover_x
|
|
while true do
|
|
self.hover_x+=dx
|
|
self.hover_x%=self.ruleset.n_slots
|
|
if (self.hover_x==orig_x) return
|
|
if (self:acceptance_state()!=acceptance_state.would_not_accept) return true
|
|
end
|
|
return
|
|
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 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
|
|
|
|
function cursor:hover_slot()
|
|
if (self.hover_y==0) return self.ruleset.n_slots+1
|
|
return self.hover_x+1
|
|
end
|
|
|
|
function cursor:grabbed_slot()
|
|
return self.grabbed_slots[#self.grabbed_slots]
|
|
end
|
|
function cursor:grabbed_card()
|
|
local grabbed_slot=self:grabbed_slot()
|
|
if grabbed_slot then
|
|
return self.board.slots[grabbed_slot]:peek()
|
|
end
|
|
end
|
|
|
|
function cursor:draw_at(l,i)
|
|
local slot=self:grabbed_slot()
|
|
|
|
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 |