Prepare for dealing out saved seeds

This commit is contained in:
2024-02-09 18:13:39 -08:00
parent 00ed414b1a
commit 05294eaa4b
14 changed files with 21068 additions and 148 deletions

View File

@ -1,4 +1,4 @@
use crate::{ruleset::{Card, CardMetadata, Setup}, smart_dealer::Deal, zobrist::{Feature, Zobrist}};
use crate::{ruleset::{Card, CardMetadata, Setup}, dumb_dealer::Deal, zobrist::{Feature, Zobrist}};
#[derive(Clone, Copy, Debug, Hash)]
pub enum Move {

View File

@ -0,0 +1,44 @@
use crate::{pico_rng::PicoRng, ruleset::{Card, Setup}};
pub struct Deal {
pub slots: Vec<Vec<Card>>,
}
impl Deal {
pub fn deal(setup: &Setup, seed: u32) -> Deal {
let n_usable_cards = setup.ruleset.usable_n_cards();
let n_usable_slots = setup.ruleset.n_slots - 1;
let tower_height = n_usable_cards / n_usable_slots;
let mut rng = PicoRng::srand(seed);
let mut slots: Vec<Vec<Card>> = vec![vec![]; n_usable_slots as usize];
let mut cards= vec![];
for i in 0..setup.deck.cards.len() {
let card = Card(i as u8);
if !setup.deck.aces.contains(&card) {
cards.push(card);
}
}
let mut slot= 0;
while cards.len() > 0 {
let n = slots.len();
let arr = &mut slots[slot % n];
let i = (rng.rnd((cards.len() * 0x10000) as u32) / 0x10000) as usize;
let card = cards[i];
if setup.deck.instantly_accepted.contains(&card) && arr.len() == 0 {
// do not use
} else {
arr.insert(0, card);
cards.remove(i);
slot += 1;
}
}
for i in 0..slots.len() {
assert_eq!(tower_height as usize, slots[i].len());
}
return Deal { slots };
}
}

View File

@ -1,39 +1,42 @@
use std::{borrow::Borrow, fs::File, io::Write, sync::{Arc, Mutex}};
use board::Board;
use pico_rng::PicoRng;
use ruleset::Ruleset;
use seen::Seen;
use crate::smart_dealer::Deal;
use crate::dumb_dealer::Deal;
mod board;
mod ruleset;
mod pico_rng;
mod seen;
mod smart_dealer;
mod dumb_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,
@ -65,15 +68,45 @@ fn main() {
}
*/
const THREADS: usize = 28;
let winnable_seeds_file = Arc::new(Mutex::new(File::create("winnable_seeds_multithreaded.txt").expect("should be able to create")));
let mut threads = Vec::new();
for i in 0..THREADS {
let setup2 = setup.clone();
let wsf = winnable_seeds_file.clone();
threads.push(std::thread::spawn(move || {
winnable_seeds_thread(
&setup2,
|seed| {
let mut f = wsf.lock().expect("must be able to lock");
write!(f, "{}\n", seed).expect("write should succeed");
f.flush().expect("flush should succeed");
},
i as u32,
THREADS as u32
);
}));
}
for i in threads {
let _ = i.join();
}
}
fn winnable_seeds_thread(setup: &ruleset::Setup, mut cb: impl FnMut(u32), start: u32, step: u32) {
let mut winnable = 0;
let mut total = 0;
loop {
for seed in (start..0xffffffff).step_by(step as usize) {
let mut board = Board::new(&setup);
board.deal(Deal::deal(&setup, &mut rand::thread_rng()));
board.deal(Deal::deal(&setup, seed));
board.display();
if is_winnable(board) {
winnable += 1;
cb(seed);
}
total += 1;
println!("winnable: {}/{} ({}%)", winnable, total, (100.0 * winnable as f32)/(total as f32));
@ -84,13 +117,19 @@ fn main() {
}
fn is_winnable(mut board: Board<'_>) -> bool {
let mut seen = Seen::new();
explore(0, &mut board, &mut seen)
return
explore(20, &mut board) ||
explore(200, &mut board)
;
}
fn explore(depth: usize, board: &mut Board<'_>, seen: &mut Seen) -> bool {
if depth > 200 {
fn explore(max_depth: usize, board: &mut Board<'_>) -> bool {
let mut seen = Seen::new();
explore2(max_depth, 0, board, &mut seen)
}
fn explore2(max_depth: usize, depth: usize, board: &mut Board<'_>, seen: &mut Seen) -> bool {
if depth > max_depth {
return false;
}
@ -108,7 +147,7 @@ fn explore(depth: usize, board: &mut Board<'_>, seen: &mut Seen) -> bool {
let hash_1 = board.zobrist_key();
board.perform(m);
// println!("try: {:X?} {:?}", board.zobrist_key(), m);
if explore(depth + 1, board, seen) {
if explore2(max_depth, depth + 1, board, seen) {
return true;
}
// println!("undo: {:X?} {:?}", board.zobrist_key(), m);

View File

@ -19,7 +19,7 @@ impl PicoRng {
pub fn rnd(&mut self, n: u32) -> u32 {
self.hi = self.hi.rotate_left(0x10).wrapping_add(self.lo);
self.lo += self.hi;
self.lo = self.lo.wrapping_add(self.hi);
return self.hi % n
}

View File

@ -1,5 +1,6 @@
use anyhow::bail;
#[derive(Clone)]
pub struct Ruleset {
pub n_slots: u8,
pub n_suits: u8,
@ -7,6 +8,7 @@ pub struct Ruleset {
pub n_arcana: u8,
}
#[derive(Clone)]
pub struct Deck {
pub aces: Vec<Card>,
pub suits: Vec<u8>,
@ -14,6 +16,7 @@ pub struct Deck {
pub instantly_accepted: Vec<Card>,
}
#[derive(Clone)]
pub struct Setup {
pub ruleset: Ruleset,
pub deck: Deck

File diff suppressed because it is too large Load Diff