pub(crate) fn can_stack(
bottom: Option<crate::solitaire::SolitaireCard>,
top: crate::solitaire::SolitaireCard,
foundation: bool,
) -> bool {
match bottom {
Some(bottom) => {
if bottom.card.color() == top.card.color() {
if foundation {
if bottom.card.eq_suite(top.card) {
match bottom.card.face() {
crate::cards::StandardCardFace::Ace => {
top.card.face() == crate::cards::StandardCardFace::Two
}
crate::cards::StandardCardFace::Two => {
top.card.face() == crate::cards::StandardCardFace::Three
}
crate::cards::StandardCardFace::Three => {
top.card.face() == crate::cards::StandardCardFace::Four
}
crate::cards::StandardCardFace::Four => {
top.card.face() == crate::cards::StandardCardFace::Five
}
crate::cards::StandardCardFace::Five => {
top.card.face() == crate::cards::StandardCardFace::Six
}
crate::cards::StandardCardFace::Six => {
top.card.face() == crate::cards::StandardCardFace::Seven
}
crate::cards::StandardCardFace::Seven => {
top.card.face() == crate::cards::StandardCardFace::Eight
}
crate::cards::StandardCardFace::Eight => {
top.card.face() == crate::cards::StandardCardFace::Nine
}
crate::cards::StandardCardFace::Nine => {
top.card.face() == crate::cards::StandardCardFace::Ten
}
crate::cards::StandardCardFace::Ten => {
top.card.face() == crate::cards::StandardCardFace::Jack
}
crate::cards::StandardCardFace::Jack => {
top.card.face() == crate::cards::StandardCardFace::Queen
}
crate::cards::StandardCardFace::Queen => {
top.card.face() == crate::cards::StandardCardFace::King
}
crate::cards::StandardCardFace::King => false,
crate::cards::StandardCardFace::Joker => unreachable!(),
}
} else {
false
}
} else {
false
}
} else if !bottom.card.eq_suite(top.card) && !foundation {
if top.is_facedown() {
false
} else if bottom.is_facedown() {
top.card.face() == crate::cards::StandardCardFace::King
} else {
match top.card.face() {
crate::cards::StandardCardFace::King => false,
crate::cards::StandardCardFace::Queen => {
bottom.card.face() == crate::cards::StandardCardFace::King
}
crate::cards::StandardCardFace::Jack => {
bottom.card.face() == crate::cards::StandardCardFace::Queen
}
crate::cards::StandardCardFace::Ten => {
bottom.card.face() == crate::cards::StandardCardFace::Joker
}
crate::cards::StandardCardFace::Nine => {
bottom.card.face() == crate::cards::StandardCardFace::Ten
}
crate::cards::StandardCardFace::Eight => {
bottom.card.face() == crate::cards::StandardCardFace::Nine
}
crate::cards::StandardCardFace::Seven => {
bottom.card.face() == crate::cards::StandardCardFace::Eight
}
crate::cards::StandardCardFace::Six => {
bottom.card.face() == crate::cards::StandardCardFace::Seven
}
crate::cards::StandardCardFace::Five => {
bottom.card.face() == crate::cards::StandardCardFace::Six
}
crate::cards::StandardCardFace::Four => {
bottom.card.face() == crate::cards::StandardCardFace::Five
}
crate::cards::StandardCardFace::Three => {
bottom.card.face() == crate::cards::StandardCardFace::Four
}
crate::cards::StandardCardFace::Two => {
bottom.card.face() == crate::cards::StandardCardFace::Three
}
crate::cards::StandardCardFace::Ace => {
bottom.card.face() == crate::cards::StandardCardFace::Two
}
crate::cards::StandardCardFace::Joker => unreachable!(),
}
}
} else {
false
}
}
None => match top.card.face() {
crate::cards::StandardCardFace::Ace => foundation && top.is_faceup(),
crate::cards::StandardCardFace::King => !foundation && top.is_faceup(),
_ => false,
},
}
}
#[cfg(test)]
mod test {
use crate::cards::{StandardCard, StandardCardFace};
use crate::solitaire::SolitaireCard;
use crate::solitaire::utils;
#[test]
fn stack_check_foundation() {
let mut top = None;
for heart in &HEARTS {
let card = SolitaireCard::new_up(*heart);
if let Some(left) = top.replace(card) {
assert!(utils::can_stack(Some(left), card, true))
}
}
let mut top = None;
for spade in &SPADES {
let card = SolitaireCard::new_up(*spade);
if let Some(left) = top.replace(card) {
assert!(utils::can_stack(Some(left), card, true))
}
}
let mut top = None;
for club in &CLUBS {
let card = SolitaireCard::new_up(*club);
if let Some(left) = top.replace(card) {
assert!(utils::can_stack(Some(left), card, true))
}
}
let mut top = None;
for diamond in &DIAMONDS {
let card = SolitaireCard::new_up(*diamond);
if let Some(left) = top.replace(card) {
assert!(utils::can_stack(Some(left), card, true))
}
}
let mut left = SolitaireCard::new_down(CLUBS[11]);
let mut right = SolitaireCard::new_up(HEARTS[12]);
assert!(!utils::can_stack(Some(left), right, true));
left.flip();
assert!(!utils::can_stack(Some(left), right, true));
left.flip();
right.flip();
assert!(!utils::can_stack(Some(left), right, true));
}
#[test]
fn stack_check() {
let mut left = SolitaireCard::new_down(CLUBS[11]);
let right = SolitaireCard::new_up(HEARTS[12]);
assert!(utils::can_stack(Some(left), right, false));
assert!(!utils::can_stack(Some(right), left, false));
left.flip();
assert!(!utils::can_stack(Some(left), right, false));
assert!(utils::can_stack(Some(right), left, false));
left = SolitaireCard::new_down(DIAMONDS[11]);
assert!(!utils::can_stack(Some(left), right, false));
assert!(!utils::can_stack(Some(right), left, false));
left.flip();
assert!(!utils::can_stack(Some(left), right, false));
assert!(!utils::can_stack(Some(right), left, false));
}
#[cfg(test)]
const HEARTS: [StandardCard; 13] = [
StandardCard::Hearts(StandardCardFace::Ace),
StandardCard::Hearts(StandardCardFace::Two),
StandardCard::Hearts(StandardCardFace::Three),
StandardCard::Hearts(StandardCardFace::Four),
StandardCard::Hearts(StandardCardFace::Five),
StandardCard::Hearts(StandardCardFace::Six),
StandardCard::Hearts(StandardCardFace::Seven),
StandardCard::Hearts(StandardCardFace::Eight),
StandardCard::Hearts(StandardCardFace::Nine),
StandardCard::Hearts(StandardCardFace::Ten),
StandardCard::Hearts(StandardCardFace::Jack),
StandardCard::Hearts(StandardCardFace::Queen),
StandardCard::Hearts(StandardCardFace::King),
];
#[cfg(test)]
const SPADES: [StandardCard; 13] = [
StandardCard::Spades(StandardCardFace::Ace),
StandardCard::Spades(StandardCardFace::Two),
StandardCard::Spades(StandardCardFace::Three),
StandardCard::Spades(StandardCardFace::Four),
StandardCard::Spades(StandardCardFace::Five),
StandardCard::Spades(StandardCardFace::Six),
StandardCard::Spades(StandardCardFace::Seven),
StandardCard::Spades(StandardCardFace::Eight),
StandardCard::Spades(StandardCardFace::Nine),
StandardCard::Spades(StandardCardFace::Ten),
StandardCard::Spades(StandardCardFace::Jack),
StandardCard::Spades(StandardCardFace::Queen),
StandardCard::Spades(StandardCardFace::King),
];
const CLUBS: [StandardCard; 13] = [
StandardCard::Clubs(StandardCardFace::Ace),
StandardCard::Clubs(StandardCardFace::Two),
StandardCard::Clubs(StandardCardFace::Three),
StandardCard::Clubs(StandardCardFace::Four),
StandardCard::Clubs(StandardCardFace::Five),
StandardCard::Clubs(StandardCardFace::Six),
StandardCard::Clubs(StandardCardFace::Seven),
StandardCard::Clubs(StandardCardFace::Eight),
StandardCard::Clubs(StandardCardFace::Nine),
StandardCard::Clubs(StandardCardFace::Ten),
StandardCard::Clubs(StandardCardFace::Jack),
StandardCard::Clubs(StandardCardFace::Queen),
StandardCard::Clubs(StandardCardFace::King),
];
const DIAMONDS: [StandardCard; 13] = [
StandardCard::Diamonds(StandardCardFace::Ace),
StandardCard::Diamonds(StandardCardFace::Two),
StandardCard::Diamonds(StandardCardFace::Three),
StandardCard::Diamonds(StandardCardFace::Four),
StandardCard::Diamonds(StandardCardFace::Five),
StandardCard::Diamonds(StandardCardFace::Six),
StandardCard::Diamonds(StandardCardFace::Seven),
StandardCard::Diamonds(StandardCardFace::Eight),
StandardCard::Diamonds(StandardCardFace::Nine),
StandardCard::Diamonds(StandardCardFace::Ten),
StandardCard::Diamonds(StandardCardFace::Jack),
StandardCard::Diamonds(StandardCardFace::Queen),
StandardCard::Diamonds(StandardCardFace::King),
];
}