Skip to content

Commit

Permalink
nits
Browse files Browse the repository at this point in the history
  • Loading branch information
mikea committed Oct 25, 2024
1 parent 1598a8b commit 0a08883
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ watch +WATCH_TARGET='run':
run:
cargo build -r
# bermuda hand
target/release/bridgitte analyze-deal --player N --strain S --stats "854.Q873.Q984.65 KQ32.T6.T72.AJ93 9.AJ542.J653.T87 AJT76.K9.AK.KQ42"
time target/release/bridgitte analyze-deal "854.Q873.Q984.65 KQ32.T6.T72.AJ93 9.AJ542.J653.T87 AJT76.K9.AK.KQ42"

clippy:
cargo clippy -- -D clippy::pedantic -A clippy::missing-panics-doc -A clippy::module_name_repetitions
Expand Down
68 changes: 58 additions & 10 deletions src/analyze.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
use std::{fmt::Debug, str::FromStr};
use std::{
fmt::{Debug, Write},
str::FromStr,
};

use rayon::prelude::*;

use crate::{
search::{search, Config},
ByPlayer, Deal, Player, Suit,
};

#[derive(Debug, Clone)]
#[derive(Clone, Copy)]
pub struct Strain {
pub trumps: Option<Suit>,
}


impl Strain {
const ALL: [Strain; 5] = [
Strain {
trumps: Some(Suit::C),
},
Strain {
trumps: Some(Suit::D),
},
Strain {
trumps: Some(Suit::H),
},
Strain {
trumps: Some(Suit::S),
},
Strain { trumps: None },
];
}

impl FromStr for Strain {
type Err = String;

Expand All @@ -33,12 +57,21 @@ impl FromStr for Strain {
}
}

#[derive(Debug)]
impl Debug for Strain {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.trumps {
Some(trumps) => f.write_str(trumps.symbol()),
None => f.write_char('N'),
}
}
}

#[derive(Debug, Clone, Copy)]
pub struct ByStrain<T> {
pub s: T,
pub h: T,
pub d: T,
pub c: T,
pub d: T,
pub h: T,
pub s: T,
pub n: T,
}

Expand All @@ -65,23 +98,38 @@ impl<T> ByStrain<T> {
}
}

impl<T: Send + Copy> ByStrain<T> {
pub fn par_new<F>(f: F) -> Self
where
F: Fn(Strain) -> T + Sync + Send,
{
let strains: Vec<_> = Strain::ALL.par_iter().map(|s| f(*s)).collect();
Self {
c: strains[0],
d: strains[1],
h: strains[2],
s: strains[3],
n: strains[4],
}
}
}

#[must_use]
pub fn analyze_all(deal: &Deal, config: &Config) -> ByPlayer<ByStrain<u8>> {
ByPlayer::new(|player| ByStrain::new(|strain| analyze(deal, player, &strain, config)))
ByPlayer::par_new(|player| ByStrain::par_new(|strain| analyze(deal, player, &strain, config)))
}

#[must_use]
pub fn analyze_strain(deal: &Deal, strain: &Strain, config: &Config) -> ByPlayer<u8> {
ByPlayer::new(|player| analyze(deal, player, strain, config))
ByPlayer::par_new(|player| analyze(deal, player, strain, config))
}

#[must_use]
pub fn analyze_player(deal: &Deal, player: Player, config: &Config) -> ByStrain<u8> {
ByStrain::new(|strain| analyze(deal, player, &strain, config))
ByStrain::par_new(|strain| analyze(deal, player, &strain, config))
}

#[must_use]
pub fn analyze(deal: &Deal, player: Player, strain: &Strain, config: &Config) -> u8 {
println!("{player:?}{:?} ", strain.trumps);
search(deal, strain.trumps, player, config)
}
6 changes: 4 additions & 2 deletions src/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ assert_eq_size!([u8; 1], Option<Suit>);

impl Suit {
pub const ALL: [Suit; 4] = [Suit::C, Suit::D, Suit::H, Suit::S];
fn symbol(&self) -> &str {

#[must_use]
pub fn symbol(&self) -> &str {
match self {
Suit::C => "\u{2663}",
Suit::D => "\u{2666}",
Expand Down Expand Up @@ -775,7 +777,7 @@ impl Deal {
}

#[must_use]
pub fn rotate_to_first(&self, player: Player) -> Deal {
pub fn rotate_to_west(&self, player: Player) -> Deal {
let i = player.index();
let hands = [
self.hands[i],
Expand Down
22 changes: 20 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
#![feature(portable_simd)]
mod cards;
use std::str::FromStr;
use rayon::prelude::*;

pub use cards::*;
mod play;
pub use play::*;
pub mod analyze;
mod bits;
pub mod counter;
pub mod search;
pub mod stats;
mod bits;

mod trans_table;

#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Player {
W = 0,
Expand All @@ -22,6 +23,8 @@ pub enum Player {
S = 3,
}
impl Player {
const ALL: [Player; 4] = [Player::W, Player::N, Player::E, Player::S];

#[must_use]
pub fn next(self) -> Player {
let idx = self as u8;
Expand Down Expand Up @@ -95,6 +98,21 @@ impl<T> ByPlayer<T> {
}
}

impl<T: Send + Copy> ByPlayer<T> {
pub fn par_new<F>(f: F) -> Self
where
F: Fn(Player) -> T + Sync + Send,
{
let players: Vec<_> = Player::ALL.par_iter().map(|s| f(*s)).collect();
Self {
w: players[0],
n: players[1],
e: players[2],
s: players[3],
}
}
}

#[derive(Debug)]
pub struct BySuit<T> {
pub s: T,
Expand Down
69 changes: 54 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use bridgitte::{
analyze::{analyze, analyze_all, analyze_player, analyze_strain, Strain}, search::Config, Deal, Player
analyze::{analyze, analyze_all, analyze_player, analyze_strain, ByStrain, Strain},
search::Config,
Deal, Player, Suit,
};
use clap::{Parser, Subcommand};

Expand Down Expand Up @@ -43,29 +45,66 @@ fn main() {
if let Some(player) = player {
if let Some(strain) = strain {
let analysis = analyze(&deal, player, &strain, &config);
dbg!(analysis);
println!("{player:?}{strain:?} {analysis}");
} else {
let analysis = analyze_player(&deal, player, &config);
dbg!(analysis);
print_by_strain(analysis, player);
}
} else if let Some(strain) = strain {
let analysis = analyze_strain(&deal, &strain, &config);
dbg!(analysis);
print_by_player(&analysis);
} else {
let analysis = analyze_all(&deal, &config);
dbg!(analysis);
print_analysis(&analysis);
}
}
}
// let trumps = Some(crate::Suit::S);
// // https://www.nytimes.com/1983/10/16/arts/bridge-bermuda-bowl-drama.html
// let deal = Deal::try_from(ByPlayer::<&str> {
// n: "KQ32.T6.T72.AJ93",
// w: "854.Q873.Q984.65",
// e: "9.AJ542.J653.T87",
// s: "AJT76.K9.AK.KQ42",
// })
// .unwrap();
}

fn print_analysis(analysis: &bridgitte::ByPlayer<ByStrain<u8>>) {
println!(
" {} {} {} {} N",
Suit::C.symbol(),
Suit::D.symbol(),
Suit::H.symbol(),
Suit::S.symbol()
);
println!(
"W {:2} {:2} {:2} {:2} {:2}",
analysis.w.c, analysis.w.d, analysis.w.h, analysis.w.s, analysis.w.n
);
println!(
"N {:2} {:2} {:2} {:2} {:2}",
analysis.n.c, analysis.n.d, analysis.n.h, analysis.n.s, analysis.n.n
);
println!(
"E {:2} {:2} {:2} {:2} {:2}",
analysis.e.c, analysis.e.d, analysis.e.h, analysis.e.s, analysis.e.n
);
println!(
"S {:2} {:2} {:2} {:2} {:2}",
analysis.s.c, analysis.s.d, analysis.s.h, analysis.s.s, analysis.s.n
);
}

fn print_by_player(analysis: &bridgitte::ByPlayer<u8>) {
println!(" W N E S");
println!(
"{:2} {:2} {:2} {:2}",
analysis.w, analysis.n, analysis.e, analysis.s
);
}

// println!("{}", search(&deal, trumps, Player::W, &Config::default()));
fn print_by_strain(analysis: ByStrain<u8>, player: Player) {
println!(
" {} {} {} {} N",
Suit::C.symbol(),
Suit::D.symbol(),
Suit::H.symbol(),
Suit::S.symbol()
);
println!(
"{player:?} {:2} {:2} {:2} {:2} {:2}",
analysis.c, analysis.d, analysis.h, analysis.s, analysis.n
);
}
12 changes: 7 additions & 5 deletions src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,15 @@ fn with_state<PoC: PlayOfCards>(state: PlayState<PoC>, config: &Config) -> u8 {
}

#[must_use]
pub fn search(deal: &Deal, trumps: Option<Suit>, player: Player, config: &Config) -> u8 {
pub fn search(deal: &Deal, trumps: Option<Suit>, declarer: Player, config: &Config) -> u8 {
let next = declarer.next();
let deal = deal.rotate_to_west(next);
if let Some(trumps) = trumps {
// trumps are always spades
let deal = deal.swap_suits(Suit::S, trumps);
with_state(PlayState::<PlayedCardsT>::new(&deal, player), config)
with_state(PlayState::<PlayedCardsT>::new(&deal, next), config)
} else {
with_state(PlayState::<PlayedCardsNT>::new(deal, player), config)
with_state(PlayState::<PlayedCardsNT>::new(&deal, next), config)
}
}

Expand Down Expand Up @@ -288,7 +290,7 @@ mod tests {
s: "72...",
})
.unwrap();
let tricks = search(&deal, None, Player::W, &Config::default());
let tricks = search(&deal, None, Player::S, &Config::default());
assert_eq!(2, tricks);
}

Expand All @@ -301,7 +303,7 @@ mod tests {
s: "752...",
})
.unwrap();
assert_eq!(2, search(&deal, None, Player::W, &Config::default()));
assert_eq!(2, search(&deal, None, Player::S, &Config::default()));
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/trans_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<PoC: PlayOfCards> From<&PlayState<PoC>> for Key {
fn from(state: &PlayState<PoC>) -> Self {
debug_assert!(state.play.is_empty());
Key {
deal: state.deal.rotate_to_first(state.next),
deal: state.deal.rotate_to_west(state.next),
}
}
}
Expand Down

0 comments on commit 0a08883

Please sign in to comment.