use board::Board; use pico_rng::PicoRng; use ruleset::Ruleset; use seen::Seen; use crate::smart_dealer::Deal; mod board; mod ruleset; mod pico_rng; mod seen; mod smart_dealer; mod zobrist; fn main() { let mut rng = PicoRng::srand(0x20000); for _ in 0..10 { println!("{}", rng.rnd(0x10000)); } return; let ruleset = Ruleset { n_slots: 11, n_suits: 5, n_cards_per_suit: 10, n_arcana: 25 }; /* let ruleset = Ruleset { n_slots: 11, n_suits: 4, n_cards_per_suit: 13, n_arcana: 22 }; */ /* let ruleset = Ruleset { n_slots: 5, n_suits: 1, n_cards_per_suit: 9, n_arcana: 0 }; */ /* let ruleset = Ruleset { n_slots: 7, n_suits: 2, n_cards_per_suit: 9, n_arcana: 8 }; */ /* let ruleset = Ruleset { n_slots: 9, n_suits: 3, n_cards_per_suit: 11, n_arcana: 18 }; */ 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); board.deal(Deal::deal(&setup, &mut rand::thread_rng())); board.display(); 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()); } fn is_winnable(mut board: Board<'_>) -> bool { let mut seen = Seen::new(); explore(0, &mut board, &mut seen) } fn explore(depth: usize, board: &mut Board<'_>, seen: &mut Seen) -> bool { if depth > 200 { return false; } if seen.contains(board.zobrist_key()) { return false } seen.add(board.zobrist_key()); if board.is_won() { board.display(); return true } for m in board.legal_moves() { let hash_1 = board.zobrist_key(); board.perform(m); // println!("try: {:X?} {:?}", board.zobrist_key(), m); if explore(depth + 1, board, seen) { return true; } // println!("undo: {:X?} {:?}", board.zobrist_key(), m); board.undo(); let hash_2 = board.zobrist_key(); assert_eq!(hash_1, hash_2) } return false; }