use super::{call, insert_uncontested, slam};
use crate::bidding::constraint::{balanced, hcp, len, stopper_in, top_honors};
use crate::bidding::{Rules, Trie};
use contract_bridge::auction::Call;
use contract_bridge::{Bid, Strain, Suit};
fn btu_responses() -> Rules {
Rules::new()
.rule(
Bid::new(4, Strain::Clubs),
3.5,
len(Suit::Hearts, 6..) & hcp(9..),
)
.rule(
Bid::new(4, Strain::Diamonds),
3.5,
len(Suit::Spades, 6..) & hcp(9..),
)
.rule(Bid::new(2, Strain::Diamonds), 3.0, len(Suit::Hearts, 5..))
.rule(Bid::new(2, Strain::Hearts), 3.0, len(Suit::Spades, 5..))
.rule(
Bid::new(3, Strain::Clubs),
2.8,
hcp(12..)
& len(Suit::Hearts, ..5)
& len(Suit::Spades, ..5)
& (len(Suit::Hearts, 4..) | len(Suit::Spades, 4..)),
)
.rule(
Bid::new(2, Strain::Clubs),
2.5,
(len(Suit::Hearts, 4..) | len(Suit::Spades, 4..)) & hcp(8..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
len(Suit::Hearts, 5..) & len(Suit::Spades, 5..) & hcp(8..),
)
.rule(
Bid::new(3, Strain::Hearts),
1.8,
len(Suit::Hearts, ..=1) & len(Suit::Spades, ..=3) & hcp(10..),
)
.rule(
Bid::new(3, Strain::Spades),
1.8,
len(Suit::Spades, ..=1) & len(Suit::Hearts, ..=3) & hcp(10..),
)
.rule(
Bid::new(2, Strain::Spades),
1.5,
len(Suit::Clubs, 6..)
| (hcp(8..=9)
& len(Suit::Hearts, ..4)
& len(Suit::Spades, ..4)
& len(Suit::Diamonds, ..5)),
)
.rule(
Bid::new(2, Strain::Notrump),
1.5,
(len(Suit::Diamonds, 5..) & len(Suit::Clubs, 4..)) | len(Suit::Diamonds, 6..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.3,
hcp(18..) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(4, Strain::Notrump),
1.2,
hcp(16..=17) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(4, Strain::Hearts),
1.1,
len(Suit::Hearts, 6..) & hcp(7..=8),
)
.rule(
Bid::new(4, Strain::Spades),
1.1,
len(Suit::Spades, 6..) & hcp(7..=8),
)
.rule(
Bid::new(3, Strain::Notrump),
1.0,
hcp(10..) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Call::Pass,
0.0,
hcp(..8)
& len(Suit::Hearts, ..5)
& len(Suit::Spades, ..5)
& len(Suit::Clubs, ..6)
& len(Suit::Diamonds, ..5),
)
}
fn btu_stayman_answers() -> Rules {
Rules::new()
.rule(Bid::new(2, Strain::Hearts), 1.0, len(Suit::Hearts, 4..))
.rule(
Bid::new(2, Strain::Spades),
1.0,
len(Suit::Spades, 4..) & len(Suit::Hearts, ..4),
)
.rule(
Bid::new(2, Strain::Diamonds),
0.5,
len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
}
fn after_2c_2d() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
3.0,
hcp(12..) & len(Suit::Spades, 5..) & len(Suit::Hearts, 4..=4),
)
.rule(
Bid::new(3, Strain::Hearts),
3.0,
hcp(12..) & len(Suit::Hearts, 5..) & len(Suit::Spades, 4..=4),
)
.rule(
Bid::new(2, Strain::Hearts),
2.5,
hcp(8..=11) & len(Suit::Spades, 5..),
)
.rule(
Bid::new(2, Strain::Spades),
2.5,
hcp(8..=11) & len(Suit::Hearts, 5..) & len(Suit::Spades, 4..=4),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
hcp(12..) & len(Suit::Clubs, 5..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
hcp(12..) & len(Suit::Diamonds, 5..),
)
.rule(
Bid::new(4, Strain::Clubs),
1.8,
len(Suit::Hearts, 6..) & len(Suit::Spades, 4..=4),
)
.rule(
Bid::new(4, Strain::Diamonds),
1.8,
len(Suit::Spades, 6..) & len(Suit::Hearts, 4..=4),
)
.rule(
Bid::new(4, Strain::Hearts),
1.5,
len(Suit::Hearts, 6..) & hcp(10..),
)
.rule(
Bid::new(4, Strain::Spades),
1.5,
len(Suit::Spades, 6..) & hcp(10..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.3,
hcp(18..) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(4, Strain::Notrump),
1.2,
hcp(16..=17) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(2, Strain::Notrump),
1.0,
hcp(8..=11) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(3, Strain::Notrump),
1.0,
hcp(12..) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(Call::Pass, 0.0, hcp(..8))
}
fn after_2c_2d_2h() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
2.0,
len(Suit::Spades, 3..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Hearts),
2.0,
len(Suit::Spades, 3..)
& len(Suit::Hearts, 4..)
& top_honors(Suit::Hearts, 2..)
& hcp(16..),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
len(Suit::Spades, 3..) & len(Suit::Clubs, 5..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
len(Suit::Spades, 3..) & len(Suit::Diamonds, 5..) & hcp(16..),
)
.rule(
Bid::new(2, Strain::Notrump),
1.5,
len(Suit::Spades, ..3) & hcp(16..),
)
.rule(Bid::new(2, Strain::Spades), 0.5, hcp(0..))
}
fn after_2c_2d_2s() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Hearts),
2.0,
len(Suit::Hearts, 3..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
len(Suit::Hearts, 3..) & len(Suit::Clubs, 5..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
len(Suit::Hearts, 3..) & len(Suit::Diamonds, 5..) & hcp(16..),
)
.rule(
Bid::new(2, Strain::Notrump),
1.0,
len(Suit::Hearts, ..3) & hcp(16..),
)
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn after_2c_2d_3h_smolen() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Spades), 1.5, len(Suit::Spades, 4..))
.rule(Bid::new(3, Strain::Notrump), 1.0, len(Suit::Hearts, ..3))
.rule(Bid::new(4, Strain::Hearts), 0.5, hcp(0..))
}
fn after_2c_2d_3s_smolen() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Hearts), 1.5, len(Suit::Hearts, 4..))
.rule(Bid::new(3, Strain::Notrump), 1.0, len(Suit::Spades, ..3))
.rule(Bid::new(4, Strain::Spades), 0.5, hcp(0..))
}
fn after_2c_2h() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
3.0,
hcp(13..) & len(Suit::Hearts, 4..),
)
.rule(
Bid::new(4, Strain::Clubs),
2.8,
hcp(12..) & len(Suit::Hearts, 4..) & len(Suit::Clubs, ..=1),
)
.rule(
Bid::new(4, Strain::Diamonds),
2.8,
hcp(12..) & len(Suit::Hearts, 4..) & len(Suit::Diamonds, ..=1),
)
.rule(
Bid::new(2, Strain::Spades),
2.5,
hcp(8..=11) & len(Suit::Spades, 5..),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
hcp(12..) & len(Suit::Hearts, ..4) & len(Suit::Clubs, 5..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
hcp(12..) & len(Suit::Hearts, ..4) & len(Suit::Diamonds, 5..),
)
.rule(
Bid::new(3, Strain::Hearts),
1.5,
hcp(8..=11) & len(Suit::Hearts, 4..),
)
.rule(
Bid::new(2, Strain::Notrump),
1.2,
hcp(8..=11) & len(Suit::Hearts, ..4) & len(Suit::Spades, 4..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.1,
hcp(18..) & len(Suit::Hearts, ..4),
)
.rule(
Bid::new(4, Strain::Notrump),
1.0,
hcp(16..=17) & len(Suit::Hearts, ..4),
)
.rule(
Bid::new(4, Strain::Hearts),
0.8,
hcp(10..=12) & len(Suit::Hearts, 4..),
)
.rule(
Bid::new(3, Strain::Notrump),
0.7,
hcp(10..) & len(Suit::Hearts, ..4),
)
.rule(Call::Pass, 0.0, hcp(..8) & len(Suit::Hearts, ..4))
}
fn after_2c_2h_2s() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
2.0,
len(Suit::Spades, 3..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Hearts),
2.0,
len(Suit::Spades, 3..)
& len(Suit::Hearts, 4..)
& top_honors(Suit::Hearts, 2..)
& hcp(16..),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
len(Suit::Spades, 3..) & len(Suit::Clubs, 5..) & hcp(16..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
len(Suit::Spades, 3..) & len(Suit::Diamonds, 5..) & hcp(16..),
)
.rule(
Bid::new(2, Strain::Notrump),
1.0,
len(Suit::Spades, ..3) & hcp(16..),
)
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn after_2c_2s() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Hearts),
3.0,
hcp(13..) & len(Suit::Spades, 4..),
)
.rule(
Bid::new(4, Strain::Clubs),
2.8,
hcp(12..) & len(Suit::Spades, 4..) & len(Suit::Clubs, ..=1),
)
.rule(
Bid::new(4, Strain::Diamonds),
2.8,
hcp(12..) & len(Suit::Spades, 4..) & len(Suit::Diamonds, ..=1),
)
.rule(
Bid::new(4, Strain::Hearts),
2.8,
hcp(12..) & len(Suit::Spades, 4..) & len(Suit::Hearts, ..=1),
)
.rule(
Bid::new(3, Strain::Clubs),
2.0,
hcp(12..) & len(Suit::Spades, ..4) & len(Suit::Clubs, 5..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
hcp(12..) & len(Suit::Spades, ..4) & len(Suit::Diamonds, 5..),
)
.rule(
Bid::new(3, Strain::Spades),
1.5,
hcp(8..=11) & len(Suit::Spades, 4..),
)
.rule(
Bid::new(2, Strain::Notrump),
1.2,
hcp(8..=11) & len(Suit::Spades, ..4) & len(Suit::Hearts, 4..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.1,
hcp(18..) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(4, Strain::Notrump),
1.0,
hcp(16..=17) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(4, Strain::Spades),
0.8,
hcp(10..=12) & len(Suit::Spades, 4..),
)
.rule(
Bid::new(3, Strain::Notrump),
0.7,
hcp(10..) & len(Suit::Spades, ..4),
)
.rule(Call::Pass, 0.0, hcp(..8) & len(Suit::Spades, ..4))
}
fn transfer_2d_answers() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Hearts),
2.5,
hcp(16..) & len(Suit::Hearts, 4..=4),
)
.rule(
Bid::new(3, Strain::Clubs),
2.5,
hcp(16..)
& len(Suit::Hearts, 4..=4)
& len(Suit::Clubs, 4..)
& top_honors(Suit::Clubs, 2..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.5,
hcp(16..)
& len(Suit::Hearts, 4..=4)
& len(Suit::Diamonds, 4..)
& top_honors(Suit::Diamonds, 2..),
)
.rule(
Bid::new(2, Strain::Spades),
2.5,
hcp(16..) & len(Suit::Hearts, 4..=4) & len(Suit::Spades, 4..=4),
)
.rule(
Bid::new(2, Strain::Notrump),
2.0,
hcp(16..) & balanced() & len(Suit::Hearts, 3..=3),
)
.rule(Bid::new(2, Strain::Hearts), 0.5, hcp(0..))
}
fn after_2d_2h() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Clubs),
3.0,
hcp(14..) & len(Suit::Hearts, 5..) & len(Suit::Clubs, 4..),
)
.rule(
Bid::new(3, Strain::Diamonds),
3.0,
hcp(14..) & len(Suit::Hearts, 5..) & len(Suit::Diamonds, 4..),
)
.rule(
Bid::new(3, Strain::Spades),
2.8,
hcp(12..) & len(Suit::Hearts, 6..) & len(Suit::Spades, ..=1),
)
.rule(
Bid::new(4, Strain::Clubs),
2.8,
hcp(12..) & len(Suit::Hearts, 6..) & len(Suit::Clubs, ..=1),
)
.rule(
Bid::new(4, Strain::Diamonds),
2.8,
hcp(12..) & len(Suit::Hearts, 6..) & len(Suit::Diamonds, ..=1),
)
.rule(
Bid::new(2, Strain::Notrump),
2.5,
hcp(12..) & !balanced() & len(Suit::Hearts, 5..),
)
.rule(
Bid::new(2, Strain::Spades),
2.0,
hcp(8..=11) & len(Suit::Hearts, 5..=5),
)
.rule(
Bid::new(3, Strain::Hearts),
1.5,
hcp(8..=11) & len(Suit::Hearts, 6..),
)
.rule(
Bid::new(4, Strain::Hearts),
1.2,
hcp(10..=13) & len(Suit::Hearts, 6..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.1,
hcp(18..) & len(Suit::Hearts, 5..) & balanced(),
)
.rule(
Bid::new(4, Strain::Notrump),
1.0,
hcp(16..=17) & len(Suit::Hearts, 5..) & balanced(),
)
.rule(
Bid::new(3, Strain::Notrump),
0.8,
hcp(10..) & balanced() & len(Suit::Hearts, 5..=5),
)
.rule(Call::Pass, 0.0, hcp(..8) & len(Suit::Hearts, 5..=5))
}
fn after_2d_2h_2s() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Hearts), 2.0, len(Suit::Hearts, 3..))
.rule(
Bid::new(3, Strain::Notrump),
2.0,
hcp(17..) & len(Suit::Hearts, ..3),
)
.rule(
Bid::new(3, Strain::Clubs),
1.8,
hcp(16..) & len(Suit::Hearts, ..3) & len(Suit::Clubs, 5..),
)
.rule(
Bid::new(3, Strain::Diamonds),
1.8,
hcp(16..) & len(Suit::Hearts, ..3) & len(Suit::Diamonds, 5..),
)
.rule(Bid::new(2, Strain::Notrump), 0.5, hcp(0..))
}
fn transfer_2h_answers() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
2.5,
hcp(16..) & len(Suit::Spades, 4..=4),
)
.rule(
Bid::new(3, Strain::Clubs),
2.5,
hcp(16..)
& len(Suit::Spades, 4..=4)
& len(Suit::Clubs, 4..)
& top_honors(Suit::Clubs, 2..),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.5,
hcp(16..)
& len(Suit::Spades, 4..=4)
& len(Suit::Diamonds, 4..)
& top_honors(Suit::Diamonds, 2..),
)
.rule(
Bid::new(3, Strain::Hearts),
2.5,
hcp(16..) & len(Suit::Spades, 4..=4) & len(Suit::Hearts, 4..=4),
)
.rule(
Bid::new(2, Strain::Notrump),
2.0,
hcp(16..) & balanced() & len(Suit::Spades, 3..=3),
)
.rule(Bid::new(2, Strain::Spades), 0.5, hcp(0..))
}
fn after_2h_2s() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Clubs),
3.0,
hcp(14..) & len(Suit::Spades, 5..) & len(Suit::Clubs, 4..),
)
.rule(
Bid::new(3, Strain::Diamonds),
3.0,
hcp(14..) & len(Suit::Spades, 5..) & len(Suit::Diamonds, 4..),
)
.rule(
Bid::new(3, Strain::Hearts),
3.0,
hcp(14..) & len(Suit::Spades, 5..) & len(Suit::Hearts, 5..),
)
.rule(
Bid::new(4, Strain::Clubs),
2.8,
hcp(12..) & len(Suit::Spades, 6..) & len(Suit::Clubs, ..=1),
)
.rule(
Bid::new(4, Strain::Diamonds),
2.8,
hcp(12..) & len(Suit::Spades, 6..) & len(Suit::Diamonds, ..=1),
)
.rule(
Bid::new(2, Strain::Notrump),
2.5,
hcp(12..) & !balanced() & len(Suit::Spades, 5..),
)
.rule(
Bid::new(3, Strain::Spades),
1.5,
hcp(8..=11) & len(Suit::Spades, 6..),
)
.rule(
Bid::new(4, Strain::Hearts),
1.3,
hcp(10..) & len(Suit::Hearts, 5..) & len(Suit::Spades, 5..),
)
.rule(
Bid::new(4, Strain::Spades),
1.2,
hcp(10..=13) & len(Suit::Spades, 6..),
)
.rule(
Bid::new(5, Strain::Notrump),
1.1,
hcp(18..) & len(Suit::Spades, 5..) & balanced(),
)
.rule(
Bid::new(4, Strain::Notrump),
1.0,
hcp(16..=17) & len(Suit::Spades, 5..) & balanced(),
)
.rule(
Bid::new(3, Strain::Notrump),
0.8,
hcp(10..) & balanced() & len(Suit::Spades, 5..=5),
)
.rule(Call::Pass, 0.0, hcp(..8) & len(Suit::Spades, 5..=5))
}
fn after_2s_club_relay() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Spades),
2.0,
hcp(16..) & len(Suit::Clubs, 4..) & stopper_in(Suit::Spades),
)
.rule(
Bid::new(3, Strain::Hearts),
2.0,
hcp(16..) & len(Suit::Clubs, 4..) & stopper_in(Suit::Hearts),
)
.rule(
Bid::new(3, Strain::Diamonds),
2.0,
hcp(16..) & len(Suit::Clubs, 4..) & stopper_in(Suit::Diamonds),
)
.rule(
Bid::new(3, Strain::Clubs),
1.5,
hcp(16..) & len(Suit::Clubs, ..=3),
)
.rule(Bid::new(2, Strain::Notrump), 0.5, hcp(0..))
}
fn after_2nt_diamond_relay() -> Rules {
Rules::new()
.rule(
Bid::new(3, Strain::Hearts),
2.0,
len(Suit::Diamonds, 5..) & stopper_in(Suit::Hearts),
)
.rule(
Bid::new(3, Strain::Spades),
2.0,
len(Suit::Diamonds, 5..) & stopper_in(Suit::Spades),
)
.rule(
Bid::new(3, Strain::Notrump),
2.0,
len(Suit::Diamonds, 5..) & stopper_in(Suit::Clubs),
)
.rule(
Bid::new(3, Strain::Diamonds),
1.0,
len(Suit::Diamonds, 3..=4),
)
.rule(Bid::new(3, Strain::Clubs), 0.5, hcp(0..))
}
fn puppet_answers() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Spades), 2.0, len(Suit::Spades, 5..))
.rule(
Bid::new(3, Strain::Hearts),
2.0,
len(Suit::Hearts, 5..) & len(Suit::Spades, ..5),
)
.rule(Bid::new(3, Strain::Diamonds), 0.5, hcp(0..))
}
fn after_puppet_3d() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Hearts), 2.0, len(Suit::Spades, 4..=4))
.rule(
Bid::new(3, Strain::Spades),
2.0,
len(Suit::Hearts, 4..=4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(4, Strain::Clubs),
1.5,
hcp(14..) & len(Suit::Hearts, 4..) & len(Suit::Spades, 4..),
)
.rule(
Bid::new(4, Strain::Diamonds),
1.2,
len(Suit::Hearts, 4..) & len(Suit::Spades, 4..),
)
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn after_puppet_3d_3h() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Spades), 1.5, len(Suit::Spades, 4..))
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn after_puppet_3d_3s() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Hearts), 1.5, len(Suit::Hearts, 4..))
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn complete_texas_hearts() -> Rules {
Rules::new().rule(Bid::new(4, Strain::Hearts), 1.0, hcp(0..))
}
fn complete_texas_spades() -> Rules {
Rules::new().rule(Bid::new(4, Strain::Spades), 1.0, hcp(0..))
}
fn quantitative_answer_1nt() -> Rules {
Rules::new()
.rule(Bid::new(6, Strain::Notrump), 1.0, hcp(17..))
.rule(Call::Pass, 0.0, hcp(0..))
}
fn quantitative_answer_5nt() -> Rules {
Rules::new()
.rule(Bid::new(7, Strain::Notrump), 1.0, hcp(17..))
.rule(Bid::new(6, Strain::Notrump), 0.5, hcp(0..))
}
fn after_3d_55_majors() -> Rules {
Rules::new()
.rule(
Bid::new(4, Strain::Hearts),
1.2,
len(Suit::Hearts, 3..) & len(Suit::Hearts, 4..),
)
.rule(Bid::new(4, Strain::Spades), 1.0, len(Suit::Spades, 3..))
.rule(Bid::new(4, Strain::Hearts), 0.8, len(Suit::Hearts, 3..))
.rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..))
}
fn after_3h_or_3s_splinter() -> Rules {
Rules::new().rule(Bid::new(3, Strain::Notrump), 1.0, hcp(0..))
}
fn reply_fg_minor() -> Rules {
Rules::new().rule(Bid::new(3, Strain::Notrump), 1.0, hcp(0..))
}
fn reply_nat_inv_2nt() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Notrump), 1.0, hcp(16..))
.rule(Call::Pass, 0.0, hcp(0..))
}
fn reply_texas_4c() -> Rules {
Rules::new().rule(Bid::new(4, Strain::Hearts), 1.0, hcp(0..))
}
fn reply_texas_4d() -> Rules {
Rules::new().rule(Bid::new(4, Strain::Spades), 1.0, hcp(0..))
}
fn reply_slam_try_hearts() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Hearts), 0.5, hcp(0..))
}
fn reply_slam_try_spades() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Spades), 0.5, hcp(0..))
}
fn reply_spl4_hearts() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Hearts), 0.5, hcp(0..))
}
fn reply_spl4_spades() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Spades), 0.5, hcp(0..))
}
fn reply_quant_5nt() -> Rules {
Rules::new()
.rule(Bid::new(7, Strain::Notrump), 1.0, hcp(17..))
.rule(Bid::new(6, Strain::Notrump), 0.5, hcp(0..))
}
fn puppet_after_3h_five() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Hearts), 0.5, hcp(0..))
}
fn puppet_after_3s_five() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, Strain::Spades), 0.5, hcp(0..))
}
pub(super) fn register(book: &mut Trie) {
let one_nt = call(1, Strain::Notrump);
insert_uncontested(book, &[one_nt], btu_responses());
let c3d_top = call(3, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c3d_top], after_3d_55_majors());
let c3h_top = call(3, Strain::Hearts);
insert_uncontested(book, &[one_nt, c3h_top], after_3h_or_3s_splinter());
let c3s_top = call(3, Strain::Spades);
insert_uncontested(book, &[one_nt, c3s_top], after_3h_or_3s_splinter());
let c2c = call(2, Strain::Clubs);
insert_uncontested(book, &[one_nt, c2c], btu_stayman_answers());
let c2d_neg = call(2, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c2c, c2d_neg], after_2c_2d());
let c2h_inv = call(2, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c2h_inv], after_2c_2d_2h());
let c2s_smolen = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c2s_smolen], after_2c_2d_2s());
let c3c_fg = call(3, Strain::Clubs);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c3c_fg], reply_fg_minor());
let c3d_fg = call(3, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c3d_fg], reply_fg_minor());
let c2nt_inv = call(2, Strain::Notrump);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c2nt_inv], reply_nat_inv_2nt());
let c4c_tex = call(4, Strain::Clubs);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c4c_tex], reply_texas_4c());
let c4d_tex = call(4, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c4d_tex], reply_texas_4d());
let c4nt_b = call(4, Strain::Notrump);
insert_uncontested(
book,
&[one_nt, c2c, c2d_neg, c4nt_b],
quantitative_answer_1nt(),
);
let c5nt_b = call(5, Strain::Notrump);
insert_uncontested(book, &[one_nt, c2c, c2d_neg, c5nt_b], reply_quant_5nt());
let c3h_smolen = call(3, Strain::Hearts);
insert_uncontested(
book,
&[one_nt, c2c, c2d_neg, c3h_smolen],
after_2c_2d_3h_smolen(),
);
let c3s_smolen = call(3, Strain::Spades);
insert_uncontested(
book,
&[one_nt, c2c, c2d_neg, c3s_smolen],
after_2c_2d_3s_smolen(),
);
let c2h = call(2, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2h], after_2c_2h());
let c2s_inv = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2c, c2h, c2s_inv], after_2c_2h_2s());
insert_uncontested(book, &[one_nt, c2c, c2h, c3c_fg], reply_fg_minor());
insert_uncontested(book, &[one_nt, c2c, c2h, c3d_fg], reply_fg_minor());
insert_uncontested(book, &[one_nt, c2c, c2h, c2nt_inv], reply_nat_inv_2nt());
let c3s_st = call(3, Strain::Spades);
insert_uncontested(book, &[one_nt, c2c, c2h, c3s_st], reply_slam_try_hearts());
slam::install_rkcb(book, &[one_nt, c2c, c2h, c3s_st], Suit::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2h, c4c_tex], reply_spl4_hearts());
slam::install_rkcb(book, &[one_nt, c2c, c2h, c4c_tex], Suit::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2h, c4d_tex], reply_spl4_hearts());
slam::install_rkcb(book, &[one_nt, c2c, c2h, c4d_tex], Suit::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2h, c4nt_b], quantitative_answer_1nt());
insert_uncontested(book, &[one_nt, c2c, c2h, c5nt_b], reply_quant_5nt());
let c2s = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2c, c2s], after_2c_2s());
insert_uncontested(book, &[one_nt, c2c, c2s, c3c_fg], reply_fg_minor());
insert_uncontested(book, &[one_nt, c2c, c2s, c3d_fg], reply_fg_minor());
insert_uncontested(book, &[one_nt, c2c, c2s, c2nt_inv], reply_nat_inv_2nt());
let c3h_st = call(3, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2s, c3h_st], reply_slam_try_spades());
slam::install_rkcb(book, &[one_nt, c2c, c2s, c3h_st], Suit::Spades);
insert_uncontested(book, &[one_nt, c2c, c2s, c4c_tex], reply_spl4_spades());
slam::install_rkcb(book, &[one_nt, c2c, c2s, c4c_tex], Suit::Spades);
insert_uncontested(book, &[one_nt, c2c, c2s, c4d_tex], reply_spl4_spades());
slam::install_rkcb(book, &[one_nt, c2c, c2s, c4d_tex], Suit::Spades);
let c4h_spl = call(4, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2c, c2s, c4h_spl], reply_spl4_spades());
slam::install_rkcb(book, &[one_nt, c2c, c2s, c4h_spl], Suit::Spades);
insert_uncontested(book, &[one_nt, c2c, c2s, c4nt_b], quantitative_answer_1nt());
insert_uncontested(book, &[one_nt, c2c, c2s, c5nt_b], reply_quant_5nt());
let c2d = call(2, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c2d], transfer_2d_answers());
let c2h_comp = call(2, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2d, c2h_comp], after_2d_2h());
let c2s_relay = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2d, c2h_comp, c2s_relay], after_2d_2h_2s());
insert_uncontested(book, &[one_nt, c2d, c2h_comp, c2nt_inv], reply_fg_minor());
let c3c_st = call(3, Strain::Clubs);
insert_uncontested(
book,
&[one_nt, c2d, c2h_comp, c3c_st],
reply_slam_try_hearts(),
);
slam::install_rkcb(book, &[one_nt, c2d, c2h_comp, c3c_st], Suit::Hearts);
let c3d_st = call(3, Strain::Diamonds);
insert_uncontested(
book,
&[one_nt, c2d, c2h_comp, c3d_st],
reply_slam_try_hearts(),
);
slam::install_rkcb(book, &[one_nt, c2d, c2h_comp, c3d_st], Suit::Hearts);
let c3s_spl = call(3, Strain::Spades);
insert_uncontested(
book,
&[one_nt, c2d, c2h_comp, c3s_spl],
reply_slam_try_hearts(),
);
slam::install_rkcb(book, &[one_nt, c2d, c2h_comp, c3s_spl], Suit::Hearts);
insert_uncontested(book, &[one_nt, c2d, c2h_comp, c4c_tex], reply_spl4_hearts());
slam::install_rkcb(book, &[one_nt, c2d, c2h_comp, c4c_tex], Suit::Hearts);
insert_uncontested(book, &[one_nt, c2d, c2h_comp, c4d_tex], reply_spl4_hearts());
slam::install_rkcb(book, &[one_nt, c2d, c2h_comp, c4d_tex], Suit::Hearts);
insert_uncontested(
book,
&[one_nt, c2d, c2h_comp, c4nt_b],
quantitative_answer_1nt(),
);
insert_uncontested(book, &[one_nt, c2d, c2h_comp, c5nt_b], reply_quant_5nt());
let c2h_trf = call(2, Strain::Hearts);
insert_uncontested(book, &[one_nt, c2h_trf], transfer_2h_answers());
let c2s_comp = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2h_trf, c2s_comp], after_2h_2s());
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c2nt_inv],
reply_fg_minor(),
);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c4c_tex],
reply_spl4_spades(),
);
slam::install_rkcb(book, &[one_nt, c2h_trf, c2s_comp, c4c_tex], Suit::Spades);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c4d_tex],
reply_spl4_spades(),
);
slam::install_rkcb(book, &[one_nt, c2h_trf, c2s_comp, c4d_tex], Suit::Spades);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c4nt_b],
quantitative_answer_1nt(),
);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c5nt_b],
reply_quant_5nt(),
);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c3c_st],
reply_slam_try_spades(),
);
slam::install_rkcb(book, &[one_nt, c2h_trf, c2s_comp, c3c_st], Suit::Spades);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c3d_st],
reply_slam_try_spades(),
);
slam::install_rkcb(book, &[one_nt, c2h_trf, c2s_comp, c3d_st], Suit::Spades);
insert_uncontested(
book,
&[one_nt, c2h_trf, c2s_comp, c3h_st],
reply_slam_try_spades(),
);
slam::install_rkcb(book, &[one_nt, c2h_trf, c2s_comp, c3h_st], Suit::Spades);
let c2s_minor = call(2, Strain::Spades);
insert_uncontested(book, &[one_nt, c2s_minor], after_2s_club_relay());
let c2nt = call(2, Strain::Notrump);
insert_uncontested(book, &[one_nt, c2nt], after_2nt_diamond_relay());
let c3c = call(3, Strain::Clubs);
insert_uncontested(book, &[one_nt, c3c], puppet_answers());
let c3d_pup = call(3, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c3c, c3d_pup], after_puppet_3d());
let c3h_pup = call(3, Strain::Hearts);
insert_uncontested(book, &[one_nt, c3c, c3d_pup, c3h_pup], after_puppet_3d_3h());
let c3s_pup = call(3, Strain::Spades);
insert_uncontested(book, &[one_nt, c3c, c3d_pup, c3s_pup], after_puppet_3d_3s());
let c3h_five = call(3, Strain::Hearts);
insert_uncontested(book, &[one_nt, c3c, c3h_five], puppet_after_3h_five());
slam::install_rkcb(book, &[one_nt, c3c, c3h_five], Suit::Hearts);
let c3s_five = call(3, Strain::Spades);
insert_uncontested(book, &[one_nt, c3c, c3s_five], puppet_after_3s_five());
slam::install_rkcb(book, &[one_nt, c3c, c3s_five], Suit::Spades);
let c4c = call(4, Strain::Clubs);
let c4d = call(4, Strain::Diamonds);
insert_uncontested(book, &[one_nt, c4c], complete_texas_hearts());
insert_uncontested(book, &[one_nt, c4d], complete_texas_spades());
let c4nt = call(4, Strain::Notrump);
let c5nt = call(5, Strain::Notrump);
insert_uncontested(book, &[one_nt, c4nt], quantitative_answer_1nt());
insert_uncontested(book, &[one_nt, c5nt], quantitative_answer_5nt());
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bidding::Rules;
use crate::bidding::context::Context;
use crate::bidding::trie::Classifier;
use contract_bridge::Hand;
use contract_bridge::auction::RelativeVulnerability;
fn best(rules: &Rules, auction: &[Call], hand: &str) -> Call {
let hand: Hand = hand.parse().expect("valid test hand");
let context = Context::new(RelativeVulnerability::NONE, auction);
let logits = rules.classify(hand, &context);
(&logits.0)
.into_iter()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).expect("logits are never NaN"))
.map(|(call, _)| call)
.expect("array is never empty")
}
const ONE_NT_P: [Call; 2] = [call(1, Strain::Notrump), Call::Pass];
#[test]
fn stayman_with_four_card_major() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "KJ52.Q7.AJ64.842"),
call(2, Strain::Clubs)
);
}
#[test]
fn transfer_to_hearts() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "73.KJ842.Q64.753"),
call(2, Strain::Diamonds)
);
}
#[test]
fn transfer_to_spades() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "KJ842.73.Q64.753"),
call(2, Strain::Hearts)
);
}
#[test]
fn minor_relay_clubs() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "73.842.64.KQJ532"),
call(2, Strain::Spades)
);
}
#[test]
fn puppet_stayman_game_force() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "AJ52.Q73.AJ6.842"),
call(3, Strain::Clubs)
);
}
#[test]
fn texas_transfer_hearts() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "73.KQ9842.AJ4.53"),
call(4, Strain::Clubs)
);
}
#[test]
fn quantitative_4nt() {
let r = btu_responses();
assert_eq!(
best(&r, &ONE_NT_P, "AK3.KQ3.Q643.Q72"),
call(4, Strain::Notrump)
);
}
#[test]
fn stayman_five_spade_invite() {
let r = after_2c_2d();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(2, Strain::Clubs),
Call::Pass,
call(2, Strain::Diamonds),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "KQ852.Q42.J63.83"),
call(2, Strain::Hearts)
);
}
#[test]
fn stayman_smolen_fg_hearts() {
let r = after_2c_2d();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(2, Strain::Clubs),
Call::Pass,
call(2, Strain::Diamonds),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "KQ52.AQ984.J6.83"),
call(3, Strain::Hearts)
);
}
#[test]
fn transfer_2d_complete() {
let r = transfer_2d_answers();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(2, Strain::Diamonds),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "AK52.Q73.KJ6.Q82"),
call(2, Strain::Hearts)
);
}
#[test]
fn transfer_2d_superaccept_3h() {
let r = transfer_2d_answers();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(2, Strain::Diamonds),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "AK2.AJ73.KJ6.Q82"),
call(3, Strain::Hearts)
);
}
#[test]
fn transfer_2h_complete() {
let r = transfer_2h_answers();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(2, Strain::Hearts),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "Q73.AK52.KJ6.Q82"),
call(2, Strain::Spades)
);
}
#[test]
fn puppet_opener_no_five_bids_3d() {
let r = puppet_answers();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(3, Strain::Clubs),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "AK52.Q73.AJ6.K82"),
call(3, Strain::Diamonds)
);
}
#[test]
fn puppet_opener_five_hearts_bids_3h() {
let r = puppet_answers();
let auction = [
call(1, Strain::Notrump),
Call::Pass,
call(3, Strain::Clubs),
Call::Pass,
];
assert_eq!(
best(&r, &auction, "AK2.AQ973.AJ6.K2"),
call(3, Strain::Hearts)
);
}
#[test]
fn no_below_game_strand() {
let mut trie = Trie::new();
register(&mut trie);
let hand: contract_bridge::Hand = "AK52.Q73.KJ6.Q82".parse().unwrap();
let sites: &[&[Call]] = &[
&[call(1, Strain::Notrump), call(3, Strain::Diamonds)],
&[call(1, Strain::Notrump), call(3, Strain::Hearts)],
&[call(1, Strain::Notrump), call(3, Strain::Spades)],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(3, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(3, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(2, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(4, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(4, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(4, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Diamonds),
call(5, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(3, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(3, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(2, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(3, Strain::Spades),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(4, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(4, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(4, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Hearts),
call(5, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(3, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(3, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(2, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(3, Strain::Hearts),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(4, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(4, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(4, Strain::Hearts),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(4, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Clubs),
call(2, Strain::Spades),
call(5, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(2, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(3, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(3, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(3, Strain::Spades),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(4, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(4, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(4, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Diamonds),
call(2, Strain::Hearts),
call(5, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Hearts),
call(2, Strain::Spades),
call(2, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Hearts),
call(2, Strain::Spades),
call(4, Strain::Clubs),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Hearts),
call(2, Strain::Spades),
call(4, Strain::Diamonds),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Hearts),
call(2, Strain::Spades),
call(4, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(2, Strain::Hearts),
call(2, Strain::Spades),
call(5, Strain::Notrump),
],
&[
call(1, Strain::Notrump),
call(3, Strain::Clubs),
call(3, Strain::Hearts),
],
&[
call(1, Strain::Notrump),
call(3, Strain::Clubs),
call(3, Strain::Spades),
],
];
for seq in sites {
let raw = super::super::uncontested(seq);
let ctx = crate::bidding::context::Context::new(
contract_bridge::auction::RelativeVulnerability::NONE,
&raw,
);
assert!(trie.resolve(&ctx, &raw).is_some(), "strand at {seq:?}");
}
let _ = hand;
}
}