use super::super::constraint::{hcp, len, min_level_is, support, they_bid};
use super::super::context::Context;
use super::super::fallback::{Fallback, FirstIs, OvercallAtMost, ReplaceNext, guard};
use super::super::{Competitive, Rules};
use super::{call, fallback_all_seats};
use contract_bridge::auction::Call;
use contract_bridge::{Bid, Strain, Suit};
use std::sync::Arc;
fn over_their_overcall(opening: Suit) -> Rules {
let o = opening;
let o_strain = Strain::from(o);
let is_major = matches!(o, Suit::Hearts | Suit::Spades);
let raise_min: usize = if is_major { 3 } else { 5 };
let jump_min: usize = if is_major { 4 } else { 5 };
let other_major = match o {
Suit::Hearts => Suit::Spades,
Suit::Spades => Suit::Hearts,
_ => Suit::Hearts, };
let mut rules = Rules::new();
for t in [Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades] {
if t == o {
continue;
}
let t_strain = Strain::from(t);
for lvl in 2u8..=3 {
rules = rules.rule(
Bid::new(lvl, t_strain),
2.0,
they_bid(t_strain) & min_level_is(lvl, t_strain) & support(raise_min..) & hcp(10..),
);
}
}
rules = rules.rule(
Bid::new(3, o_strain),
1.6,
min_level_is(2, o_strain) & support(jump_min..) & hcp(..=9),
);
rules = rules.rule(
Bid::new(3, o_strain),
1.3,
min_level_is(3, o_strain) & support(raise_min..) & hcp(6..=9),
);
rules = rules.rule(
Bid::new(2, o_strain),
1.5,
min_level_is(2, o_strain) & support(raise_min..) & hcp(6..=9),
);
rules = if is_major {
rules.rule(Call::Double, 1.0, len(other_major, 4..) & hcp(8..))
} else {
rules.rule(
Call::Double,
1.0,
len(Suit::Hearts, 4..) & len(Suit::Spades, 4..) & hcp(8..),
)
};
for x in [Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades] {
if x == o {
continue;
}
let x_strain = Strain::from(x);
for lvl in 2u8..=3 {
rules = rules.rule(
Bid::new(lvl, x_strain),
1.1,
min_level_is(lvl - 1, x_strain) & len(x, 6..) & hcp(2..=5) & !they_bid(x_strain),
);
}
}
rules.rule(Call::Pass, 0.0, hcp(0..))
}
fn support_rules(major: Suit) -> Rules {
let m = Strain::from(major);
Rules::new()
.rule(Call::Double, 1.5, support(3..=3))
.rule(Bid::new(2, m), 1.4, support(4..))
.rule(Call::Pass, 0.0, hcp(0..))
}
fn answer_neg_double_of_minor(opening_major: Suit) -> Rules {
let m = Strain::from(opening_major);
let other = if opening_major == Suit::Hearts {
Suit::Spades
} else {
Suit::Hearts
};
let other_strain = Strain::from(other);
Rules::new()
.rule(Bid::new(2, other_strain), 1.0, len(other, 3..))
.rule(Bid::new(2, m), 0.5, len(opening_major, 5..))
}
#[must_use]
pub fn competition() -> Competitive {
let mut book = Competitive::new();
for opening in [Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades] {
let opening_call = call(1, Strain::from(opening));
fallback_all_seats(
&mut book,
&[opening_call],
3,
Arc::new(OvercallAtMost(Bid::new(2, Strain::Spades))),
Fallback::classify(over_their_overcall(opening)),
);
fallback_all_seats(
&mut book,
&[opening_call],
3,
Arc::new(FirstIs(Call::Double)),
Fallback::rebase(ReplaceNext(Call::Pass)),
);
}
for minor in [Suit::Clubs, Suit::Diamonds] {
for major in [Suit::Hearts, Suit::Spades] {
let suffix = [
call(1, Strain::from(minor)),
Call::Pass,
call(1, Strain::from(major)),
];
let just_below = if major == Suit::Hearts {
Bid::new(2, Strain::Diamonds)
} else {
Bid::new(2, Strain::Hearts)
};
fallback_all_seats(
&mut book,
&suffix,
3,
Arc::new(OvercallAtMost(just_below)),
Fallback::classify(support_rules(major)),
);
fallback_all_seats(
&mut book,
&suffix,
3,
Arc::new(guard(|_: &Context<'_>, suffix: &[Call]| {
suffix == [Call::Double]
})),
Fallback::classify({
let m = Strain::from(major);
Rules::new()
.rule(Call::Redouble, 1.5, support(3..=3))
.rule(Bid::new(2, m), 1.4, support(4..))
.rule(Call::Pass, 0.0, hcp(0..))
}),
);
}
}
for major in [Suit::Hearts, Suit::Spades] {
fallback_all_seats(
&mut book,
&[call(1, Strain::from(major))],
3,
Arc::new(guard(|_: &Context<'_>, suffix: &[Call]| {
matches!(
suffix,
[Call::Bid(b), Call::Double, Call::Pass]
if b.level.get() == 2
&& (b.strain == Strain::Clubs || b.strain == Strain::Diamonds)
)
})),
Fallback::classify(answer_neg_double_of_minor(major)),
);
}
book
}