Further improvements to the smart dealer
This commit is contained in:
parent
89b0dce6b9
commit
0b3d45378f
@ -1,6 +1,6 @@
|
|||||||
progression={
|
progression={
|
||||||
-- level 1
|
-- level 1
|
||||||
--ruleset:new(5,1,9,0),
|
-- ruleset:new(5,1,9,0),
|
||||||
-- level 2
|
-- level 2
|
||||||
-- ruleset:new(5,2,9,0),
|
-- ruleset:new(5,2,9,0),
|
||||||
-- level 3
|
-- level 3
|
||||||
|
@ -80,13 +80,21 @@ impl<'a> Board<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn display(&self) {
|
pub fn display(&self) {
|
||||||
|
fn display_cards(setup: &Setup, cards: &[Card]) {
|
||||||
|
print!("- ");
|
||||||
|
for c in cards {
|
||||||
|
let meta = setup.deck.cards[c.0 as usize];
|
||||||
|
print!("{}{:02} ", meta.suit as char, meta.rank);
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
println!("Wells:");
|
println!("Wells:");
|
||||||
for w in &self.wells {
|
for w in &self.wells {
|
||||||
println!("- {:?}", w.contents);
|
display_cards(self.setup, &w.contents);
|
||||||
}
|
}
|
||||||
println!("\nSlots:");
|
println!("\nSlots:");
|
||||||
for s in &self.slots {
|
for s in &self.slots {
|
||||||
println!("- {:?}", s.contents);
|
display_cards(self.setup, &s.contents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,20 +12,20 @@ mod zobrist;
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
/*
|
||||||
let ruleset = Ruleset {
|
let ruleset = Ruleset {
|
||||||
n_slots: 11,
|
n_slots: 11,
|
||||||
n_suits: 5,
|
n_suits: 5,
|
||||||
n_cards_per_suit: 10,
|
n_cards_per_suit: 10,
|
||||||
n_arcana: 25
|
n_arcana: 25
|
||||||
};
|
};
|
||||||
/*
|
*/
|
||||||
let ruleset = Ruleset {
|
let ruleset = Ruleset {
|
||||||
n_slots: 11,
|
n_slots: 11,
|
||||||
n_suits: 4,
|
n_suits: 4,
|
||||||
n_cards_per_suit: 13,
|
n_cards_per_suit: 13,
|
||||||
n_arcana: 22
|
n_arcana: 22
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
let ruleset = Ruleset {
|
let ruleset = Ruleset {
|
||||||
n_slots: 5,
|
n_slots: 5,
|
||||||
@ -51,11 +51,25 @@ fn main() {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
let setup = ruleset.compile().expect("compilation should succeed");
|
let setup = ruleset.compile().expect("compilation should succeed");
|
||||||
|
/*
|
||||||
|
for _ in 0..10000 {
|
||||||
|
Deal::deal(&setup, &mut rand::thread_rng());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
let mut winnable = 0;
|
||||||
|
let mut total = 0;
|
||||||
|
loop {
|
||||||
let mut board = Board::new(&setup);
|
let mut board = Board::new(&setup);
|
||||||
board.deal(Deal::deal(&setup, &mut rand::thread_rng()));
|
board.deal(Deal::deal(&setup, &mut rand::thread_rng()));
|
||||||
board.display();
|
board.display();
|
||||||
|
|
||||||
println!("is_winnable: {}", is_winnable(board));
|
if is_winnable(board) {
|
||||||
|
winnable += 1;
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
println!("winnable: {}/{} ({}%)", winnable, total, (100.0 * winnable as f32)/(total as f32));
|
||||||
|
}
|
||||||
|
|
||||||
// println!("Legal moves: {:#?}", board.legal_moves());
|
// println!("Legal moves: {:#?}", board.legal_moves());
|
||||||
|
|
||||||
|
@ -17,10 +17,11 @@ impl Deal {
|
|||||||
fn deal1(setup: &Setup, rng: &mut impl Rng) -> Option<Deal> {
|
fn deal1(setup: &Setup, rng: &mut impl Rng) -> Option<Deal> {
|
||||||
// don't use the middle slot
|
// don't use the middle slot
|
||||||
let n_slots = (setup.ruleset.n_slots - 1) as usize;
|
let n_slots = (setup.ruleset.n_slots - 1) as usize;
|
||||||
|
let aux_slot = n_slots;
|
||||||
let n_usable_cards = setup.ruleset.usable_n_cards();
|
let n_usable_cards = setup.ruleset.usable_n_cards();
|
||||||
let tower_height = n_usable_cards as usize / n_slots;
|
let tower_height = n_usable_cards as usize / n_slots;
|
||||||
|
|
||||||
let mut slots: Vec<Vec<Card>> = vec![vec![]; n_slots];
|
let mut slots: Vec<Vec<Card>> = vec![vec![]; n_slots+1];
|
||||||
|
|
||||||
let split_point =
|
let split_point =
|
||||||
if setup.ruleset.n_arcana == 0 { 0 }
|
if setup.ruleset.n_arcana == 0 { 0 }
|
||||||
@ -53,18 +54,20 @@ impl Deal {
|
|||||||
}
|
}
|
||||||
pops.shuffle(rng);
|
pops.shuffle(rng);
|
||||||
|
|
||||||
while let Some(w) = pops.pop() {
|
fn find_home(card: Card, exclude: Option<usize>, setup: &Setup, slots: &mut [Vec<Card>], aux_slot: usize, tower_height: usize, rng: &mut impl Rng) {
|
||||||
fn find_home(card: Card, exclude: Option<usize>, setup: &Setup, slots: &mut [Vec<Card>], tower_height: usize, rng: &mut impl Rng) {
|
|
||||||
let mut acceptors = vec![];
|
let mut acceptors = vec![];
|
||||||
let mut not_full = vec![];
|
let mut not_full = vec![];
|
||||||
for s in 0..slots.len() {
|
for s in 0..slots.len() {
|
||||||
if Some(s) != exclude && slots[s].len() < tower_height {
|
let not_too_tall = slots[s].len() < if s == aux_slot { 1 } else { tower_height };
|
||||||
if accepts(setup, slots[s].last().cloned(), card) {
|
if Some(s) != exclude {
|
||||||
|
if not_too_tall && accepts(setup, slots[s].last().cloned(), card) {
|
||||||
acceptors.push(s)
|
acceptors.push(s)
|
||||||
}
|
}
|
||||||
|
if not_too_tall {
|
||||||
not_full.push(s);
|
not_full.push(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
acceptors.shuffle(rng);
|
acceptors.shuffle(rng);
|
||||||
not_full.shuffle(rng);
|
not_full.shuffle(rng);
|
||||||
@ -79,11 +82,13 @@ impl Deal {
|
|||||||
panic!("should not ever happen")
|
panic!("should not ever happen")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Some(w) = pops.pop() {
|
||||||
let card = virtual_wells[w].pop().expect("card must be present");
|
let card = virtual_wells[w].pop().expect("card must be present");
|
||||||
find_home(card, None, setup, &mut slots, tower_height, rng);
|
find_home(card, None, setup, &mut slots, aux_slot, tower_height, rng);
|
||||||
|
|
||||||
// move any card that is on an acceptor to a random slot
|
// move any card that is on an acceptor to a random slot
|
||||||
for _ in 0..4 {
|
for _ in 0..15 {
|
||||||
let mut sources: Vec<usize> = (0..slots.len()).collect();
|
let mut sources: Vec<usize> = (0..slots.len()).collect();
|
||||||
sources.shuffle(rng);
|
sources.shuffle(rng);
|
||||||
for src in sources {
|
for src in sources {
|
||||||
@ -94,13 +99,19 @@ impl Deal {
|
|||||||
if let Some(t) = top {
|
if let Some(t) = top {
|
||||||
if accepts(&setup, second_to_top, t) {
|
if accepts(&setup, second_to_top, t) {
|
||||||
slots[src].pop();
|
slots[src].pop();
|
||||||
find_home(t, Some(src), setup, &mut slots, tower_height, rng);
|
find_home(t, Some(src), setup, &mut slots, aux_slot, tower_height, rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(top) = slots[n_slots].pop() {
|
||||||
|
assert!(slots[n_slots].len() == 0);
|
||||||
|
find_home(top, Some(n_slots), setup, &mut slots, aux_slot, tower_height, rng);
|
||||||
|
assert!(slots[n_slots].len() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
let mut instantly_accepted = vec![];
|
let mut instantly_accepted = vec![];
|
||||||
for &a in &setup.deck.aces {
|
for &a in &setup.deck.aces {
|
||||||
instantly_accepted.push(Card(a.0 + 1)) // twos
|
instantly_accepted.push(Card(a.0 + 1)) // twos
|
||||||
@ -108,9 +119,7 @@ impl Deal {
|
|||||||
instantly_accepted.push(Card(first_arcana));
|
instantly_accepted.push(Card(first_arcana));
|
||||||
instantly_accepted.push(Card(first_arcana + setup.ruleset.n_arcana - 1));
|
instantly_accepted.push(Card(first_arcana + setup.ruleset.n_arcana - 1));
|
||||||
|
|
||||||
// NOTE: We never used the free cell. The free cell can dig one deeper
|
for s in 0..n_slots {
|
||||||
// So in theory most of these deals should be solvable using the freecell
|
|
||||||
for s in 0..slots.len() {
|
|
||||||
let mut iter = slots[s].iter().rev();
|
let mut iter = slots[s].iter().rev();
|
||||||
let last = iter.next().cloned();
|
let last = iter.next().cloned();
|
||||||
let second_to_last = iter.next().cloned();
|
let second_to_last = iter.next().cloned();
|
||||||
@ -132,6 +141,13 @@ impl Deal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for s in 0..n_slots {
|
||||||
|
assert!(slots[s].len() == tower_height)
|
||||||
|
}
|
||||||
|
|
||||||
|
slots.pop(); // get rid of aux slot
|
||||||
|
|
||||||
return Some(Deal { slots });
|
return Some(Deal { slots });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user