Prepare for dealing out saved seeds
This commit is contained in:
@ -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 {
|
||||
|
44
simulator/src/dumb_dealer.rs
Normal file
44
simulator/src/dumb_dealer.rs
Normal 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 };
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
10347
simulator/winnable_seeds_multithreaded.txt
Normal file
10347
simulator/winnable_seeds_multithreaded.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user