diff --git a/dealer.lua b/dealer.lua index 9b3e642..843b687 100644 --- a/dealer.lua +++ b/dealer.lua @@ -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(card,allow_too_tall) assert(card!=0) local acceptors={} local start_points={} @@ -57,31 +57,9 @@ function deal(ruleset) 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 w=pop(pops) 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 + find_home(card,true) end -- fix any stacks that are too tall @@ -89,14 +67,27 @@ 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(card,false)) return end end -- get rid of auxiliary slot slots[0]=nil + local shuffles=1 + local actual_shuffles=1 + for s=1,#slots do + local extra_shuf=shuffles+1 + while (ruleset.deck.instantly_accepted[pek(slots[s])]) do + shuf(slots[s]) + shuffles=extra_shuf + actual_shuffles+=1 + if (actual_shuffles>=5) return nil + end + end + for i=shuffles,2 do + shuf(rnd(slots)) + end for s=1,#slots do - if (ruleset.deck.instantly_accepted[pek(slots[s])]) return assert(#slots[s]==tower_height) end diff --git a/simulator/src/smart_dealer.rs b/simulator/src/smart_dealer.rs index be8d5cf..45cbad8 100644 --- a/simulator/src/smart_dealer.rs +++ b/simulator/src/smart_dealer.rs @@ -31,7 +31,7 @@ impl Deal { while let Some((w, n)) = pops.pop() { for _ in 0..n { let card = wells[w].pop().expect("card must be present"); - Self::find_home(setup, rng, card, None, None, &mut slots, &max_height, true); + Self::find_home(setup, rng, card, &mut slots, &max_height, true); } } @@ -40,7 +40,7 @@ impl Deal { for i in 0..slots.len() { while slots[i].len() > max_height[i] { let card = slots[i].pop().expect("must be a card"); - Self::find_home(setup, rng, card, None, None, &mut slots, &max_height, false); + Self::find_home(setup, rng, card, &mut slots, &max_height, false); } } @@ -127,28 +127,21 @@ impl Deal { rle } - fn find_home(setup: &Setup, rng: &mut impl Rng, card: Card, source: Option, exclude: Option, slots: &mut [Vec], max_height: &[usize], allow_too_tall: bool) { + fn find_home(setup: &Setup, rng: &mut impl Rng, card: Card, slots: &mut [Vec], max_height: &[usize], allow_too_tall: bool) { // if a card is sitting on an acceptor, it could have been moved there // from somewhere else let mut acceptors = vec![]; for s in 0..slots.len() { - if Some(s) == exclude { - // don't place it here, ever - } else if false { // slots[s].len() == max_height[s] - 1 && setup.deck.instantly_accepted.contains(&card) { - // can't place an instantly accepted card at the bottom of a slot - } else { - if allow_too_tall && accepts(setup, slots[s].last().cloned(), card) { - acceptors.push(s); - } else if slots[s].len() < max_height[s] { - acceptors.push(s); - } + if (allow_too_tall && accepts(setup, slots[s].last().cloned(), card)) || + slots[s].len() < max_height[s] { + acceptors.push(s); } } let acceptor = acceptors.choose(rng).cloned(); - if let Some(a) = acceptor.or(source) { + if let Some(a) = acceptor { slots[a].push(card); } else { panic!("should never happen")