Skip to main content

compute_hot_deals/
main.rs

1use dds_bridge::contract::Strain;
2use dds_bridge::deal::{Card, Deal, Hand, Seat, SmallSet as _, Suit};
3use dds_bridge::solver;
4use rand::RngExt as _;
5use std::process::ExitCode;
6
7/// Generate a hand with one card of each rank
8fn get_random_average_hand(rng: &mut (impl rand::Rng + ?Sized)) -> Hand {
9    let bits: u64 = rng.random();
10
11    (0..13).fold(Hand::EMPTY, |mut hand, i| {
12        // SAFETY: we are slicing valid consecutive 2 bits from `bits`
13        let suit: Suit = unsafe { core::mem::transmute((bits >> (2 * i) & 3) as u8) };
14        hand.insert(Card::new(suit, i + 2));
15        hand
16    })
17}
18
19fn get_random_symmetric_deal(rng: &mut (impl rand::Rng + ?Sized)) -> Deal {
20    let hand = get_random_average_hand(rng);
21    let sequence = [
22        hand.0[1], hand.0[2], hand.0[3], hand.0[0], hand.0[1], hand.0[2],
23    ];
24    let north = hand;
25    let east = Hand(sequence[0..4].try_into().expect("Invalid hand"));
26    let south = Hand(sequence[1..5].try_into().expect("Invalid hand"));
27    let west = Hand(sequence[2..6].try_into().expect("Invalid hand"));
28    Deal([north, east, south, west])
29}
30
31fn compute_deal(
32    rng: &mut (impl rand::Rng + ?Sized),
33) -> Result<(Deal, solver::TricksTable), solver::Error> {
34    const N: usize = dds_bridge_sys::MAXNOOFTABLES as usize;
35    loop {
36        let deals: [_; N] = core::array::from_fn(|_| get_random_symmetric_deal(rng));
37        // SAFETY: `N` is exactly the maximum length of a deal segment.
38        let tables = unsafe { solver::solve_deal_segment(&deals, solver::StrainFlags::all())? };
39
40        for (i, &table) in tables.results[..N].iter().enumerate() {
41            let tricks = solver::TricksTable::from(table);
42            let pars = solver::calculate_pars(tricks, solver::Vulnerability::all())?;
43
44            if pars[0].score + pars[1].score > 0 {
45                return Ok((deals[i], tricks));
46            }
47        }
48    }
49}
50
51#[doc = include_str!("README.md")]
52fn main() -> Result<ExitCode, solver::Error> {
53    let deals = match std::env::args().nth(1) {
54        Some(string) => {
55            if let Ok(n) = string.parse::<usize>() {
56                n
57            } else {
58                eprintln!("{}", include_str!("README.md"));
59                return Ok(ExitCode::FAILURE);
60            }
61        }
62        None => 1,
63    };
64
65    for _ in 0..deals {
66        let (deal, tricks) = compute_deal(&mut rand::rng())?;
67        println!(
68            "{} {:X}",
69            deal.display(Seat::North),
70            tricks.hex(Seat::North, Strain::SYS)
71        );
72    }
73
74    Ok(ExitCode::SUCCESS)
75}