Port smart dealer 1
This commit is contained in:
parent
37d39b4521
commit
dbd9c600c8
156
dealer.lua
Normal file
156
dealer.lua
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
function deal(ruleset)
|
||||||
|
local n_usable_cards=ruleset.n_usable_cards
|
||||||
|
local n_final_slots=ruleset.n_slots-1
|
||||||
|
local n_usable_slots=n_final_slots+1
|
||||||
|
local tower_height = n_usable_cards\n_final_slots
|
||||||
|
|
||||||
|
-- prototype
|
||||||
|
local deal1,generate_wells,generate_pops,accepts
|
||||||
|
local deal1=function()
|
||||||
|
local slots,max_height={},{}
|
||||||
|
for i=0,n_final_slots do
|
||||||
|
slots[i]={}
|
||||||
|
max_height[i]=tower_height
|
||||||
|
end
|
||||||
|
max_height[0]=1
|
||||||
|
|
||||||
|
local wells=generate_wells()
|
||||||
|
local pops=generate_pops(wells)
|
||||||
|
|
||||||
|
local function pek(lst)
|
||||||
|
return lst[#lst]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pop(lst)
|
||||||
|
return deli(lst,#lst)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pop_accepted_card(lst)
|
||||||
|
local card=lst[#lst]
|
||||||
|
if (card and accepts(lst[#lst-1],card)) return pop(lst)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_home(odds,card,source,exclude)
|
||||||
|
assert(card!=0)
|
||||||
|
local acceptors={}
|
||||||
|
local start_points={}
|
||||||
|
|
||||||
|
for s=0,#slots do
|
||||||
|
local n=#slots[s]
|
||||||
|
if s==exclude then
|
||||||
|
-- don't place it here ever
|
||||||
|
elseif ruleset.deck.instantly_accepted[card] and n==max_height[s]-1 then
|
||||||
|
-- can't place an instantly accepted card at the bottom of a slot
|
||||||
|
else
|
||||||
|
if (accepts(pek(slots[s]),card)) add(acceptors,s)
|
||||||
|
if (n<max_height[s]) add(start_points,s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local acceptor=rnd(acceptors)
|
||||||
|
local start_point=rnd(start_points)
|
||||||
|
if (acceptor and rnd()>odds) acceptor=nil
|
||||||
|
|
||||||
|
local a=acceptor or start_point or source
|
||||||
|
if (a) add(slots[a],card) return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local original_pops=#pops
|
||||||
|
while #pops>0 do
|
||||||
|
local w=deli(pops)
|
||||||
|
assert(w!=0)
|
||||||
|
local exclude
|
||||||
|
|
||||||
|
-- unblock aux slot if this is not arcana
|
||||||
|
if w <= ruleset.n_suits then
|
||||||
|
local c=pop(slots[0])
|
||||||
|
assert(c!=0)
|
||||||
|
if (c and not find_home(1.0,c,nil,0)) return
|
||||||
|
exclude = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local card=pop(wells[w])
|
||||||
|
assert(card!=0)
|
||||||
|
if (not find_home(1.0,card,nil,exclude)) return
|
||||||
|
|
||||||
|
local n_moves=48
|
||||||
|
for i=1,n_moves do
|
||||||
|
local src=flr(rnd()*(#slots+1))
|
||||||
|
local card=pop_accepted_card(slots[src])
|
||||||
|
if card then
|
||||||
|
local odds=0.0
|
||||||
|
if (not find_home(odds,card,src,nil)) return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fix any stacks that are too tall
|
||||||
|
max_height[0]=0 -- auxiliary slot must be empty
|
||||||
|
for i=0,#slots do
|
||||||
|
while #slots[i]>max_height[i] do
|
||||||
|
local card=pop(slots[i])
|
||||||
|
if (not find_home(0.0,card,nil,nil)) return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get rid of auxiliary slot
|
||||||
|
slots[0]=nil
|
||||||
|
for s=1,#slots do
|
||||||
|
if (ruleset.deck.instantly_accepted[pek(slots[s])]) return
|
||||||
|
assert(#slots[s]==tower_height)
|
||||||
|
end
|
||||||
|
|
||||||
|
return slots
|
||||||
|
end
|
||||||
|
generate_wells=function()
|
||||||
|
local split_point=flr(rnd()*(ruleset.n_arcana+1))
|
||||||
|
local wells={}
|
||||||
|
for i=1,ruleset.n_suits+2 do
|
||||||
|
wells[i]={}
|
||||||
|
end
|
||||||
|
for r=2,ruleset.n_cards_per_suit do
|
||||||
|
for s=1,ruleset.n_suits do
|
||||||
|
local card=ruleset.n_cards_per_suit * (s - 1) + (r - 1) + 1
|
||||||
|
assert(card!=0)
|
||||||
|
add(wells[s],card)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local first_arcana=ruleset.n_suits*ruleset.n_cards_per_suit+1
|
||||||
|
local arcana0=ruleset.n_suits
|
||||||
|
local arcana1=arcana0+1
|
||||||
|
for r=0,split_point-1 do
|
||||||
|
assert(first_arcana+r!=0)
|
||||||
|
add(wells[arcana0],first_arcana+r)
|
||||||
|
end
|
||||||
|
for r=ruleset.n_arcana-1,split_point,-1 do
|
||||||
|
assert(first_arcana+r!=0)
|
||||||
|
add(wells[arcana1],first_arcana+r)
|
||||||
|
end
|
||||||
|
return wells
|
||||||
|
end
|
||||||
|
generate_pops=function(wells)
|
||||||
|
local pops={}
|
||||||
|
for w=1,#wells do
|
||||||
|
for _=1,#wells[w] do
|
||||||
|
add(pops,w)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
shuf(pops)
|
||||||
|
return pops
|
||||||
|
end
|
||||||
|
accepts=function(c0,c1)
|
||||||
|
assert(c0!=0)
|
||||||
|
assert(c1!=0)
|
||||||
|
assert(c1!=nil)
|
||||||
|
if (c0==nil) return true
|
||||||
|
c0=ruleset.deck.cards[c0]
|
||||||
|
c1=ruleset.deck.cards[c1]
|
||||||
|
return c0.suit==c1.suit and (c1.rank == c0.rank+1 or c0.rank==c1.rank+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local d=deal1()
|
||||||
|
if (d) return d
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user