use super::super::Rules;
use super::super::Trie;
use super::super::constraint::{balanced, hcp, len, stopper_in, support};
use contract_bridge::auction::Call;
use contract_bridge::{Bid, Strain, Suit};
#[must_use]
pub fn major_responses(major: Suit) -> Rules {
let trump = Strain::from(major);
let mut rules = Rules::new()
.rule(Bid::new(2, Strain::Notrump), 3.0, support(4..) & hcp(13..))
.rule(Bid::new(3, trump), 2.0, support(4..) & hcp(10..=12))
.rule(Bid::new(4, trump), 1.6, support(5..) & hcp(..6))
.rule(Bid::new(2, trump), 1.5, support(3..) & hcp(6..=9))
.rule(Bid::new(1, Strain::Notrump), 0.5, hcp(6..=12))
.rule(Call::Pass, 0.0, hcp(..6));
if major == Suit::Hearts {
rules = rules.rule(
Bid::new(1, Strain::Spades),
1.7,
len(Suit::Spades, 4..) & hcp(6..) & !support(4..),
);
}
let splinter_suits: &[Suit] = if major == Suit::Hearts {
&[Suit::Spades, Suit::Clubs, Suit::Diamonds]
} else {
&[Suit::Clubs, Suit::Diamonds, Suit::Hearts]
};
for &x in splinter_suits {
let (level, strain) = splinter_bid(major, x);
rules = rules.rule(
Bid::new(level, strain),
2.8,
support(4..) & hcp(10..=13) & len(x, ..=1),
);
}
let wjs_suits: &[Suit] = if major == Suit::Hearts {
&[Suit::Spades, Suit::Clubs, Suit::Diamonds]
} else {
&[Suit::Clubs, Suit::Diamonds, Suit::Hearts]
};
for &x in wjs_suits {
let (level, strain) = wjs_bid(major, x);
rules = rules.rule(Bid::new(level, strain), 1.0, len(x, 6..) & hcp(2..=5));
}
let mut weight = 1.1;
for suit in [Suit::Clubs, Suit::Diamonds, Suit::Hearts] {
if Strain::from(suit) < trump {
rules = rules.rule(
Bid::new(2, Strain::from(suit)),
weight,
len(suit, 4..) & hcp(13..) & !support(4..),
);
weight -= 0.05;
}
}
rules
}
fn splinter_bid(major: Suit, x: Suit) -> (u8, Strain) {
let major_strain = Strain::from(major);
let x_strain = Strain::from(x);
if x_strain > major_strain {
(3, x_strain)
} else {
(4, x_strain)
}
}
fn wjs_bid(major: Suit, x: Suit) -> (u8, Strain) {
let major_strain = Strain::from(major);
let x_strain = Strain::from(x);
if x_strain > major_strain {
(2, x_strain)
} else {
(3, x_strain)
}
}
#[must_use]
pub fn minor_responses(minor: Suit) -> Rules {
let trump = Strain::from(minor);
let mut rules = Rules::new()
.rule(
Bid::new(1, Strain::Hearts),
1.5,
len(Suit::Hearts, 4..) & hcp(6..),
)
.rule(
Bid::new(1, Strain::Spades),
1.4,
len(Suit::Spades, 4..) & hcp(6..) & len(Suit::Hearts, ..4),
)
.rule(
Bid::new(3, Strain::Notrump),
1.0,
hcp(13..) & balanced() & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(2, Strain::Notrump),
1.0,
hcp(11..=12) & balanced() & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(1, Strain::Notrump),
0.5,
hcp(6..=10) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(
Bid::new(2, trump),
1.25,
support(5..) & hcp(10..) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
)
.rule(Bid::new(3, trump), 1.1, support(5..) & hcp(..=9))
.rule(Call::Pass, 0.0, hcp(..6));
for x in [Suit::Hearts, Suit::Spades] {
rules = rules.rule(Bid::new(2, Strain::from(x)), 1.0, len(x, 6..) & hcp(2..=5));
}
if minor == Suit::Diamonds {
rules = rules.rule(
Bid::new(2, Strain::Clubs),
1.3,
len(Suit::Clubs, 4..) & hcp(13..) & len(Suit::Hearts, ..4) & len(Suit::Spades, ..4),
);
}
rules
}
pub(super) fn register(book: &mut Trie) {
for major in [Suit::Hearts, Suit::Spades] {
super::insert_uncontested(
book,
&[super::call(1, Strain::from(major))],
major_responses(major),
);
}
for minor in [Suit::Clubs, Suit::Diamonds] {
super::insert_uncontested(
book,
&[super::call(1, Strain::from(minor))],
minor_responses(minor),
);
}
for major in [Suit::Hearts, Suit::Spades] {
let m_strain = Strain::from(major);
let splinter_suits: &[Suit] = if major == Suit::Hearts {
&[Suit::Spades, Suit::Clubs, Suit::Diamonds]
} else {
&[Suit::Clubs, Suit::Diamonds, Suit::Hearts]
};
for &x in splinter_suits {
let (level, strain) = splinter_bid(major, x);
let splinter = super::call(level, strain);
let our_calls = &[super::call(1, m_strain), splinter];
let after_splinter = Rules::new()
.rule(Bid::new(4, Strain::Notrump), 1.0, hcp(16..))
.rule(Bid::new(4, m_strain), 0.5, hcp(0..));
super::insert_uncontested(book, our_calls, after_splinter);
super::slam::install_rkcb(book, our_calls, major);
}
}
for minor in [Suit::Clubs, Suit::Diamonds] {
let m_strain = Strain::from(minor);
let our_calls = &[super::call(1, m_strain), super::call(2, m_strain)];
let after_inv_raise = Rules::new()
.rule(Bid::new(2, Strain::Notrump), 1.0, hcp(12..=14) & balanced())
.rule(Bid::new(3, Strain::Notrump), 1.0, hcp(18..=19))
.rule(
Bid::new(2, Strain::Hearts),
0.8,
stopper_in(Suit::Hearts) & hcp(15..),
)
.rule(
Bid::new(2, Strain::Spades),
0.8,
stopper_in(Suit::Spades) & hcp(15..),
)
.rule(Bid::new(3, m_strain), 0.5, hcp(0..));
super::insert_uncontested(book, our_calls, after_inv_raise);
let after_2nt = Rules::new()
.rule(Bid::new(3, Strain::Notrump), 1.0, hcp(13..))
.rule(Bid::new(3, m_strain), 0.5, hcp(0..));
let our_calls_2nt = &[
super::call(1, m_strain),
super::call(2, m_strain),
super::call(2, Strain::Notrump),
];
super::insert_uncontested(book, our_calls_2nt, after_2nt);
for major in [Suit::Hearts, Suit::Spades] {
let major_strain = Strain::from(major);
let after_major = Rules::new()
.rule(Bid::new(3, Strain::Notrump), 1.0, hcp(13..))
.rule(Bid::new(2, Strain::Notrump), 0.8, hcp(10..=12))
.rule(Bid::new(3, m_strain), 0.5, hcp(0..));
let our_calls_major = &[
super::call(1, m_strain),
super::call(2, m_strain),
super::call(2, major_strain),
];
super::insert_uncontested(book, our_calls_major, after_major);
let after_2nt_4th = Rules::new().rule(Bid::new(3, Strain::Notrump), 0.5, hcp(0..));
let our_calls_2nt_4th = &[
super::call(1, m_strain),
super::call(2, m_strain),
super::call(2, major_strain),
super::call(2, Strain::Notrump),
];
super::insert_uncontested(book, our_calls_2nt_4th, after_2nt_4th);
}
}
}