Try another smart dealer implementation

This commit is contained in:
Pyrex 2024-02-07 21:07:53 -08:00
parent dbd9c600c8
commit e4e6887e64
4 changed files with 36 additions and 71 deletions

View File

@ -44,64 +44,24 @@ function board:init(ruleset)
end
function board:deal()
local deal=deal(self.ruleset)
local n_usable_slots=self.ruleset.n_slots - 1
-- first, pull the aces
local available={}
for card=1,#self.ruleset.deck.cards do
available[card]=true
end
for i=1,#self.ruleset.deck.aces do
local well=self.wells[i]
local ace=self.ruleset.deck.aces[i]
well:add(ace) -- temporarily, so would_accept will work
self:animate_move_ace_to_well(ace,i)
available[ace]=false
end
local eligible_bottom_row={}
for card=1,#self.ruleset.deck.cards do
local skip
if not available[card] then
skip=true
else
for w in all(self.wells) do
if (w:would_accept(card)) skip=true break
local rows=#deal[1]
for y=1,rows do
for x=1,#deal do
local outx=x
if (x>n_usable_slots\2) outx+=1
self:animate_move_new_card_to_slot(deal[x][y],outx)
end
end
if (not skip) add(eligible_bottom_row,card)
end
-- let the animation install the aces for real
for w in all(self.wells) do
w:clear()
end
function i_to_slot(i)
if (i<n_usable_slots\2) return i+1
return i+2
end
local bottom_row={}
shuf(eligible_bottom_row)
for i=1,n_usable_slots do
local card=eligible_bottom_row[i]
add(bottom_row,card)
available[card]=false
end
eligible={}
for card=1,#self.ruleset.deck.cards do
if (available[card]) add(eligible,card)
end
shuf(eligible)
for card in all(bottom_row) do
add(eligible,card)
end
for i=1,#eligible do
local ix=i_to_slot((i-1)%n_usable_slots)
local slot=self.slots[ix]
self:animate_move_new_card_to_slot(eligible[i],ix)
end
end
function board:on_idle()

View File

@ -30,7 +30,7 @@ function deal(ruleset)
if (card and accepts(lst[#lst-1],card)) return pop(lst)
end
local function find_home(odds,card,source,exclude)
local function find_home(prefer_acceptor,card,source,exclude,ignore_acceptorhood)
assert(card!=0)
local acceptors={}
local start_points={}
@ -41,17 +41,20 @@ function deal(ruleset)
-- 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
elseif not ignore_acceptorhood and accepts(pek(slots[s]),card) then
add(acceptors,s)
elseif n<max_height[s] then
add(start_points,s)
end
end
local a
if prefer_acceptor then
a=rnd(acceptors) or rnd(start_points) or source
else
if (accepts(pek(slots[s]),card)) add(acceptors,s)
if (n<max_height[s]) add(start_points,s)
end
a=rnd(start_points) or rnd(acceptors) or source
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
@ -65,22 +68,18 @@ function deal(ruleset)
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
if (c and not find_home(false,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
if (not find_home(true,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
if (not find_home(false,card,src,nil)) return
end
end
@ -89,7 +88,7 @@ function deal(ruleset)
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
if (not find_home(false,card,nil,nil,true)) return
end
end

View File

@ -9,6 +9,7 @@ __lua__
#include layout.lua
#include ruleset.lua
#include progression.lua
#include dealer.lua
#include main.lua
__gfx__
00000000070000007770000000700000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

View File

@ -32,17 +32,19 @@ function ruleset:init(
local usable_slots = n_slots - 1
assert(usable_slots%2==0)
local total_n_cards = n_arcana + n_suits * n_cards_per_suit
local n_total_cards = n_arcana + n_suits * n_cards_per_suit
-- aces aren't usable because they are initially placed in the wells
local usable_n_cards = total_n_cards - self.n_suits
local n_usable_cards = n_total_cards - self.n_suits
-- deal has to be symmetrical
assert(usable_n_cards % usable_slots == 0, usable_slots-(usable_n_cards%usable_slots))
assert(n_usable_cards % usable_slots == 0, usable_slots-(n_usable_cards%usable_slots))
-- these cards would be instantly moved to the wells and
-- therefore cannot be in the bottom row
local instantly_placed_cards = self.n_suits + 2
assert((total_n_cards-instantly_placed_cards)-usable_slots >= 0)
assert((n_total_cards-instantly_placed_cards)-usable_slots >= 0)
self.n_usable_cards = n_usable_cards
self:generate_deck()
self:generate_layouts()
@ -55,6 +57,7 @@ function ruleset:generate_deck()
aces={},
suits={},
cards={},
instantly_accepted={},
rank_name="a23456789tjqk"
}
self.deck=deck
@ -67,12 +70,14 @@ function ruleset:generate_deck()
for rank=1,self.n_cards_per_suit do
add(deck.cards,{suit=suit,rank=rank})
if (rank==1) add(deck.aces,#deck.cards)
if (rank==2) deck.instantly_accepted[#deck.cards]=true
end
end
-- arcana
for rank=0,self.n_arcana-1 do
add(deck.cards,{suit="a",rank=rank})
if (rank==0 or rank==self.n_arcana-1) deck.instantly_accepted[#deck.cards]=true
end
function deck:draw_card(x,y,c,shadow)