pub struct MonteCarloBot<R: Rng> { /* private fields */ }Expand description
A determinized Monte Carlo player
At every decision the bot samples hidden worlds consistent with its
View — the opponent holds every card they are known to have taken,
and the remaining unseen cards are distributed between their hand and
the stock, biased toward the meld-rich hands a real opponent collects —
plays each world out with the greedy policy on both seats, and picks
the action with the best expected value for the game: each rollout’s
result lands on the running game scores, a
result that reaches game_target counts as the
win or loss of the game it is, and anything short of one counts its
round points. The same worlds are reused across candidate actions
(common random numbers), and the bot deviates from the greedy baseline
only when the paired samples show a statistically clear gain. Worlds
are rolled in growing batches, and a challenger the incumbent already
statistically dominates is dropped at a batch boundary — once none
remain, the remaining worlds are never rolled at all — so an easy
decision costs a fraction of the full sample count.
The bot owns its random number generator, so a seeded generator makes its play reproducible.
Implementations§
Source§impl<R: Rng> MonteCarloBot<R>
impl<R: Rng> MonteCarloBot<R>
Sourcepub const fn samples(self, samples: u32) -> Self
pub const fn samples(self, samples: u32) -> Self
Set how many worlds each decision samples
More samples play stronger and slower. At the default of 128 the
bot wins about 65% of decisive rounds against the default
HeuristicBot — which is tuned for whole-game play and so concedes
single rounds — at roughly 10 ms per average turn in release builds
(easy decisions stop at a fraction of the budget; a hard first
discard, where every shed stays plausible, runs the full count for
~25 ms); 32 keeps a smaller edge at a quarter of the cost. The
parallel feature divides any of these by most of a machine’s
cores.
Sourcepub fn assess(&mut self, view: &View<'_>) -> Vec<Assessment>
pub fn assess(&mut self, view: &View<'_>) -> Vec<Assessment>
Assess every candidate action for the current decision, each with its Monte Carlo equity and expected round points, ranked by equity with the bot’s own pick flagged — the read a solver or hint view shows
The candidates and the flagged pick mirror the matching Strategy
method on the same sampled worlds, so the recommended row is the move
the bot would play — with one deliberate contraction: a knock’s shed
is not a real choice (dropping the largest deadwood is always the best
knock), so the discard phase lists a single knock rather than one per
shed. Returns empty when the seat has no real choice: a forced stock
draw, the layoff phase, or a finished round.
Trait Implementations§
Source§impl<R: Rng> Strategy for MonteCarloBot<R>
impl<R: Rng> Strategy for MonteCarloBot<R>
Source§fn offer_upcard(&mut self, view: &View<'_>) -> UpcardAction
fn offer_upcard(&mut self, view: &View<'_>) -> UpcardAction
Source§fn choose_draw(&mut self, view: &View<'_>) -> DrawAction
fn choose_draw(&mut self, view: &View<'_>) -> DrawAction
Source§fn play_turn(&mut self, view: &View<'_>) -> TurnAction
fn play_turn(&mut self, view: &View<'_>) -> TurnAction
Auto Trait Implementations§
impl<R> Freeze for MonteCarloBot<R>where
R: Freeze,
impl<R> RefUnwindSafe for MonteCarloBot<R>where
R: RefUnwindSafe,
impl<R> Send for MonteCarloBot<R>where
R: Send,
impl<R> Sync for MonteCarloBot<R>where
R: Sync,
impl<R> Unpin for MonteCarloBot<R>where
R: Unpin,
impl<R> UnsafeUnpin for MonteCarloBot<R>where
R: UnsafeUnpin,
impl<R> UnwindSafe for MonteCarloBot<R>where
R: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more