use super::{call, insert_uncontested};
use crate::bidding::constraint::{hcp, len};
use crate::bidding::{Rules, Trie};
use contract_bridge::auction::Call;
use contract_bridge::{Bid, Strain, Suit};
#[must_use]
pub fn notrump_responses() -> Rules {
Rules::new()
.rule(Bid::new(2, Strain::Diamonds), 2.0, len(Suit::Hearts, 5..))
.rule(Bid::new(2, Strain::Hearts), 2.0, len(Suit::Spades, 5..))
.rule(
Bid::new(2, Strain::Clubs),
1.5,
(len(Suit::Hearts, 4..=4) | len(Suit::Spades, 4..=4)) & hcp(8..),
)
.rule(
Bid::new(4, Strain::Notrump),
1.2,
hcp(16..=17) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(3, Strain::Notrump),
1.0,
hcp(10..) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(2, Strain::Notrump),
1.0,
hcp(8..=9) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Call::Pass,
0.0,
hcp(..8) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
}
fn 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 complete_transfer(into: Suit) -> Rules {
Rules::new().rule(Bid::new(2, Strain::from(into)), 1.0, hcp(0..))
}
fn two_notrump_responses() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Diamonds), 2.0, len(Suit::Hearts, 5..))
.rule(Bid::new(3, Strain::Hearts), 2.0, len(Suit::Spades, 5..))
.rule(
Bid::new(3, Strain::Clubs),
1.5,
(len(Suit::Hearts, 4..=4) | len(Suit::Spades, 4..=4)) & hcp(5..),
)
.rule(
Bid::new(4, Strain::Notrump),
1.2,
hcp(11..=12) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(
Bid::new(3, Strain::Notrump),
1.0,
hcp(5..=10) & len(Suit::Hearts, ..5) & len(Suit::Spades, ..5),
)
.rule(Call::Pass, 0.0, hcp(..5))
}
fn stayman_answers_at_three() -> Rules {
Rules::new()
.rule(Bid::new(3, Strain::Hearts), 1.0, len(Suit::Hearts, 4..))
.rule(
Bid::new(3, Strain::Spades),
1.0,
len(Suit::Spades, 4..) & len(Suit::Hearts, ..4),
)
.rule(
Bid::new(3, Strain::Diamonds),
0.5,
len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
}
fn complete_transfer_at_three(into: Suit) -> Rules {
Rules::new().rule(Bid::new(3, Strain::from(into)), 1.0, hcp(0..))
}
fn quantitative_answer(accept_hcp: u8) -> Rules {
Rules::new()
.rule(Bid::new(6, Strain::Notrump), 1.0, hcp(accept_hcp..))
.rule(Call::Pass, 0.0, hcp(0..))
}
fn after_rebid_two_notrump() -> Rules {
Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.2, hcp(12..=13))
.rule(Bid::new(3, Strain::Notrump), 1.0, hcp(6..))
.rule(Call::Pass, 0.0, hcp(..6))
}
fn accept_quantitative_nineteen() -> Rules {
Rules::new()
.rule(Bid::new(6, Strain::Notrump), 1.0, hcp(19..))
.rule(Call::Pass, 0.0, hcp(0..))
}
pub(super) fn register(book: &mut Trie) {
register_one_nt(book);
register_two_nt_and_rebids(book);
}
pub(super) fn register_one_nt(book: &mut Trie) {
let one_nt = call(1, Strain::Notrump);
let four_nt = call(4, Strain::Notrump);
insert_uncontested(book, &[one_nt], notrump_responses());
insert_uncontested(book, &[one_nt, call(2, Strain::Clubs)], stayman_answers());
insert_uncontested(
book,
&[one_nt, call(2, Strain::Diamonds)],
complete_transfer(Suit::Hearts),
);
insert_uncontested(
book,
&[one_nt, call(2, Strain::Hearts)],
complete_transfer(Suit::Spades),
);
insert_uncontested(book, &[one_nt, four_nt], quantitative_answer(17));
}
pub(super) fn register_two_nt_and_rebids(book: &mut Trie) {
let one_nt = call(1, Strain::Notrump);
let two_nt = call(2, Strain::Notrump);
let four_nt = call(4, Strain::Notrump);
let bases: &[(&[Call], u8)] = &[
(&[two_nt], 21),
(
&[call(2, Strain::Clubs), call(2, Strain::Diamonds), two_nt],
24,
),
(
&[call(2, Strain::Clubs), call(2, Strain::Hearts), two_nt],
24,
),
];
for (base, accept_hcp) in bases {
insert_uncontested(book, base, two_notrump_responses());
let extend = |tail: Call| -> Vec<Call> {
base.iter().copied().chain(core::iter::once(tail)).collect()
};
insert_uncontested(
book,
&extend(call(3, Strain::Clubs)),
stayman_answers_at_three(),
);
insert_uncontested(
book,
&extend(call(3, Strain::Diamonds)),
complete_transfer_at_three(Suit::Hearts),
);
insert_uncontested(
book,
&extend(call(3, Strain::Hearts)),
complete_transfer_at_three(Suit::Spades),
);
insert_uncontested(book, &extend(four_nt), quantitative_answer(*accept_hcp));
}
let rebid_prefixes: &[&[Call]] = &[
&[call(1, Strain::Hearts), call(1, Strain::Spades)],
&[call(1, Strain::Clubs), call(1, Strain::Diamonds)],
&[call(1, Strain::Clubs), call(1, Strain::Hearts)],
&[call(1, Strain::Clubs), call(1, Strain::Spades)],
&[call(1, Strain::Diamonds), call(1, Strain::Hearts)],
&[call(1, Strain::Diamonds), call(1, Strain::Spades)],
&[call(1, Strain::Hearts), one_nt],
&[call(1, Strain::Spades), one_nt],
];
for prefix in rebid_prefixes {
let mut our = prefix.to_vec();
our.push(two_nt);
insert_uncontested(book, &our, after_rebid_two_notrump());
our.push(four_nt);
insert_uncontested(book, &our, accept_quantitative_nineteen());
}
}