Compare commits
3 Commits
30884d7c35
...
ee895d81eb
| Author | SHA1 | Date | |
|---|---|---|---|
| ee895d81eb | |||
| b3b9fb61a5 | |||
| e86c705b5b |
@@ -148,8 +148,6 @@ impl Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_be_placed_on_foundation(&self, top: &Option<Card>) -> Result<(), StackingError> {
|
pub fn can_be_placed_on_foundation(&self, top: &Option<Card>) -> Result<(), StackingError> {
|
||||||
// TODO check suit is correct
|
|
||||||
println!("hello1");
|
|
||||||
match top {
|
match top {
|
||||||
None => {
|
None => {
|
||||||
if self.value == Value::Ace {
|
if self.value == Value::Ace {
|
||||||
@@ -160,7 +158,6 @@ impl Card {
|
|||||||
},
|
},
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
if self.suit != c.suit {
|
if self.suit != c.suit {
|
||||||
println!("hellosuitsame");
|
|
||||||
return Err(StackingError::WrongSuit);
|
return Err(StackingError::WrongSuit);
|
||||||
}
|
}
|
||||||
if self.value.indexed_values() + 1 == c.value.indexed_values() {
|
if self.value.indexed_values() + 1 == c.value.indexed_values() {
|
||||||
@@ -223,7 +220,6 @@ pub struct CardAndPosition {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum CardPosition {
|
pub enum CardPosition {
|
||||||
Deck, // I don't think this will need to be used
|
|
||||||
TopWaste, // I don't think we'd ever interact with anything other than the top of the Waste
|
TopWaste, // I don't think we'd ever interact with anything other than the top of the Waste
|
||||||
Pile(usize, usize), // (PileNumber, Index)
|
Pile(usize, usize), // (PileNumber, Index)
|
||||||
Foundation(usize)
|
Foundation(usize)
|
||||||
@@ -280,7 +276,6 @@ impl Klondike {
|
|||||||
// TODO raise errors properly
|
// TODO raise errors properly
|
||||||
assert!(source_card.card.is_some());
|
assert!(source_card.card.is_some());
|
||||||
assert_eq!(source_card.card.unwrap().visible, true);
|
assert_eq!(source_card.card.unwrap().visible, true);
|
||||||
source_card.pos.is_valid_source();
|
|
||||||
dest_card.pos.is_valid_dest();
|
dest_card.pos.is_valid_dest();
|
||||||
|
|
||||||
// Maybe TODO - check the .cards is the actual card in that position
|
// Maybe TODO - check the .cards is the actual card in that position
|
||||||
@@ -288,12 +283,13 @@ impl Klondike {
|
|||||||
match dest_card.pos {
|
match dest_card.pos {
|
||||||
CardPosition::Pile(_, _) => self.move_card_to_pile(&source_card, &dest_card),
|
CardPosition::Pile(_, _) => self.move_card_to_pile(&source_card, &dest_card),
|
||||||
CardPosition::Foundation(_f) => self.move_card_to_foundation(source_card, dest_card),
|
CardPosition::Foundation(_f) => self.move_card_to_foundation(source_card, dest_card),
|
||||||
CardPosition::Deck | CardPosition::TopWaste => unreachable!()
|
CardPosition::TopWaste => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_card_to_foundation(mut self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
|
pub fn move_card_to_foundation(mut self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
|
||||||
// TODO Check whether the card is the top of a pile / waste - it needs to be
|
// TODO check the cards referenced in source and dest are the ones that are actually there
|
||||||
|
// TODO - ditto this for the "move to pile" function
|
||||||
// TODO actually learn Rust properly so I can figure out why I need to clone the whole struct to check a value
|
// TODO actually learn Rust properly so I can figure out why I need to clone the whole struct to check a value
|
||||||
if source_card.pos != CardPosition::TopWaste && !self.clone().is_card_top_of_pile(&source_card.pos) {
|
if source_card.pos != CardPosition::TopWaste && !self.clone().is_card_top_of_pile(&source_card.pos) {
|
||||||
// TODO as above - make all these proper errors
|
// TODO as above - make all these proper errors
|
||||||
@@ -302,8 +298,7 @@ impl Klondike {
|
|||||||
if source_card.card.unwrap().can_be_placed_on_foundation(&dest_card.card).is_err() {
|
if source_card.card.unwrap().can_be_placed_on_foundation(&dest_card.card).is_err() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO actually move the cards - it should be possible from here
|
|
||||||
// There really must be a better way to extract an enum "value" than this...
|
|
||||||
if let CardPosition::Foundation(foundation_index) = dest_card.pos {
|
if let CardPosition::Foundation(foundation_index) = dest_card.pos {
|
||||||
match source_card.pos {
|
match source_card.pos {
|
||||||
CardPosition::TopWaste => {
|
CardPosition::TopWaste => {
|
||||||
@@ -316,7 +311,7 @@ impl Klondike {
|
|||||||
self.foundation[foundation_index].push(card);
|
self.foundation[foundation_index].push(card);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
CardPosition::Deck | CardPosition::Foundation(_) => {
|
CardPosition::Foundation(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -324,7 +319,42 @@ impl Klondike {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_card_to_pile(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
|
pub fn move_card_to_pile(mut self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
|
||||||
|
if source_card.card.unwrap().can_be_placed_on_pile(&dest_card.card.unwrap()).is_err() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let (dpile_index, dcard_index) = match dest_card.pos {
|
||||||
|
CardPosition::Pile(p, i) => (p, i),
|
||||||
|
CardPosition::TopWaste | CardPosition::Foundation(_) => return false
|
||||||
|
};
|
||||||
|
if dcard_index != self.piles[dpile_index].len() - 1 {
|
||||||
|
// Can't move to anything other than top of pile
|
||||||
|
// this should already have been checked in the is_card_top...
|
||||||
|
// maybe I'll just delete this check...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
match source_card.pos {
|
||||||
|
CardPosition::TopWaste => {
|
||||||
|
let card = self.waste.pop().unwrap();
|
||||||
|
self.piles[dpile_index].push(card);
|
||||||
|
},
|
||||||
|
CardPosition::Pile(spile_index, scard_index) => {
|
||||||
|
let num_cards_to_take = self.piles[spile_index].len() - scard_index; // -1 maybe?
|
||||||
|
let mut cards: Vec<Card> = Vec::new();
|
||||||
|
for _ in 0..num_cards_to_take {
|
||||||
|
cards.push(self.piles[spile_index].pop().unwrap());
|
||||||
|
}
|
||||||
|
for card in cards {
|
||||||
|
self.piles[dpile_index].push(card);
|
||||||
|
}
|
||||||
|
// TODO Properly learn rust and why I can't use drain & extend methods
|
||||||
|
// https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain
|
||||||
|
},
|
||||||
|
CardPosition::Foundation(s_index) => {
|
||||||
|
let card = self.foundation[s_index].pop().unwrap();
|
||||||
|
self.piles[dpile_index].push(card);
|
||||||
|
},
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +364,6 @@ impl Klondike {
|
|||||||
CardPosition::Pile(pile_index, card_index) => {
|
CardPosition::Pile(pile_index, card_index) => {
|
||||||
match self.piles.get(*pile_index) {
|
match self.piles.get(*pile_index) {
|
||||||
Some(pile_index) => {
|
Some(pile_index) => {
|
||||||
// TODO - this is the correct palce to put a - 1
|
|
||||||
if *card_index == (pile_index.len() - 1) {
|
if *card_index == (pile_index.len() - 1) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -344,27 +373,19 @@ impl Klondike {
|
|||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CardPosition::Deck | CardPosition::TopWaste | CardPosition::Foundation(_) => false
|
CardPosition::TopWaste | CardPosition::Foundation(_) => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardPosition {
|
impl CardPosition {
|
||||||
// Unsure this is "correct" to just panic - but it really shouldn't happen
|
|
||||||
fn is_valid_dest(&self) {
|
fn is_valid_dest(&self) {
|
||||||
|
// TODO as with many other places - should probably raise an error instead of panic
|
||||||
match self {
|
match self {
|
||||||
CardPosition::Deck => panic!("You can't move cards to deck"),
|
|
||||||
CardPosition::TopWaste => panic!("You can't move cards to waste"),
|
CardPosition::TopWaste => panic!("You can't move cards to waste"),
|
||||||
CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (),
|
CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_source(&self) {
|
|
||||||
match self {
|
|
||||||
CardPosition::Deck => panic!("You can't move cards from deck"),
|
|
||||||
CardPosition::TopWaste | CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Klondike {
|
impl Default for Klondike {
|
||||||
@@ -626,8 +647,53 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn klondike() {
|
fn move_pile_card_to_good_pile() {
|
||||||
let k = Klondike::default();
|
let mut klon = Klondike::default();
|
||||||
//println!("{:#?}", k);
|
let ace = Card {
|
||||||
|
suit: Suit::Heart,
|
||||||
|
value: Value::Ace,
|
||||||
|
.. Default::default()
|
||||||
|
};
|
||||||
|
let two = Card {
|
||||||
|
suit: Suit::Spade,
|
||||||
|
value: Value::Two,
|
||||||
|
.. Default::default()
|
||||||
|
};
|
||||||
|
klon.piles[0].push(two.clone());
|
||||||
|
klon.piles[1].push(ace.clone());
|
||||||
|
let source_card = CardAndPosition {
|
||||||
|
card: Some(ace.clone()),
|
||||||
|
pos: CardPosition::Pile(1, 2),
|
||||||
|
};
|
||||||
|
let dest_card = CardAndPosition {
|
||||||
|
card: Some(two.clone()),
|
||||||
|
pos: CardPosition::Pile(0, 1),
|
||||||
|
};
|
||||||
|
assert!(klon.move_card_to_pile(&source_card, &dest_card));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn move_pile_card_to_bad_pile() {
|
||||||
|
let mut klon = Klondike::default();
|
||||||
|
let ace = Card {
|
||||||
|
suit: Suit::Heart,
|
||||||
|
value: Value::Ace,
|
||||||
|
.. Default::default()
|
||||||
|
};
|
||||||
|
let two = Card {
|
||||||
|
suit: Suit::Diamond,
|
||||||
|
value: Value::Two,
|
||||||
|
.. Default::default()
|
||||||
|
};
|
||||||
|
klon.piles[0].push(two.clone());
|
||||||
|
klon.piles[1].push(ace.clone());
|
||||||
|
let source_card = CardAndPosition {
|
||||||
|
card: Some(ace.clone()),
|
||||||
|
pos: CardPosition::Pile(1, 2),
|
||||||
|
};
|
||||||
|
let dest_card = CardAndPosition {
|
||||||
|
card: Some(two.clone()),
|
||||||
|
pos: CardPosition::Pile(0, 1),
|
||||||
|
};
|
||||||
|
assert!(!klon.move_card_to_pile(&source_card, &dest_card));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use ratatui::{
|
|||||||
layout::{Constraint, Layout, Rect, Flex},
|
layout::{Constraint, Layout, Rect, Flex},
|
||||||
style::{Style, Stylize, Color},
|
style::{Style, Stylize, Color},
|
||||||
text::Line,
|
text::Line,
|
||||||
widgets::{Block, BorderType, Borders, Paragraph},
|
widgets::{Block, BorderType, Borders, Paragraph, Clear, Wrap},
|
||||||
DefaultTerminal, Frame,
|
DefaultTerminal, Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ pub struct App {
|
|||||||
// I should think about making this a Vec so I can highlight a whole stack which is about to move
|
// I should think about making this a Vec so I can highlight a whole stack which is about to move
|
||||||
selected_card: Option<card_stuffs::Card>,
|
selected_card: Option<card_stuffs::Card>,
|
||||||
exit: bool,
|
exit: bool,
|
||||||
|
show_help: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CARD_HEIGHT: u16 = 11;
|
const CARD_HEIGHT: u16 = 11;
|
||||||
@@ -69,26 +70,6 @@ fn draw_waste(cards_in_waste: &Vec<card_stuffs::Card>, area: Rect, frame: &mut F
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deck_widget(cards_in_deck: &Vec<card_stuffs::Card>) -> Paragraph<'static> {
|
|
||||||
let card_image = format!(
|
|
||||||
"#############\n\
|
|
||||||
#############\n\
|
|
||||||
### Cards ###\n\
|
|
||||||
### Left ###\n\
|
|
||||||
#############\n\
|
|
||||||
#### {:02} #####\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############", cards_in_deck.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
Paragraph::new(card_image)
|
|
||||||
.block(Block::new()
|
|
||||||
.borders(Borders::ALL)
|
|
||||||
.border_type(BorderType::Rounded))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, select: bool) -> Paragraph<'a> {
|
fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, select: bool) -> Paragraph<'a> {
|
||||||
if !card.visible {
|
if !card.visible {
|
||||||
return facedown_card(top);
|
return facedown_card(top);
|
||||||
@@ -121,80 +102,6 @@ fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, sele
|
|||||||
.border_type(BorderType::Rounded))
|
.border_type(BorderType::Rounded))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partially_covered_card(card: &card_stuffs::Card) -> Paragraph {
|
|
||||||
let card_image = format!(
|
|
||||||
"{value}{suit}", value=card.value, suit=card.suit
|
|
||||||
);
|
|
||||||
let card_style = match card.suit.colour() {
|
|
||||||
card_stuffs::Colour::Black => Style::new().black().bg(Color::White),
|
|
||||||
card_stuffs::Colour::Red => Style::new().red().bg(Color::White),
|
|
||||||
};
|
|
||||||
let borders = Borders::TOP | Borders::LEFT | Borders::BOTTOM;
|
|
||||||
let border_style = Style::new().white().on_black();
|
|
||||||
Paragraph::new(card_image)
|
|
||||||
.style(card_style)
|
|
||||||
.block(Block::new()
|
|
||||||
.style(border_style)
|
|
||||||
.borders(borders)
|
|
||||||
.border_type(BorderType::Rounded))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct CardWidget {
|
|
||||||
card: card_stuffs::Card,
|
|
||||||
// put display stuff in here?
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Widget for CardWidget {
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
||||||
let mut border_style = Style::default();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn facedown_card(top: bool) -> Paragraph<'static> {
|
|
||||||
let hidden_card = format!(
|
|
||||||
"#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############\n\
|
|
||||||
#############"
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut borders = Borders::TOP | Borders::LEFT | Borders::RIGHT;
|
|
||||||
if top {
|
|
||||||
borders |= Borders::BOTTOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
Paragraph::new(hidden_card)
|
|
||||||
.block(Block::new()
|
|
||||||
.borders(borders)
|
|
||||||
.border_type(BorderType::Rounded))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn empty_pile() -> Paragraph<'static> {
|
|
||||||
// made using https://www.asciiart.eu/
|
|
||||||
let hidden_card = format!(
|
|
||||||
"
|
|
||||||
XX XX
|
|
||||||
XX XX
|
|
||||||
|
|
||||||
X X
|
|
||||||
X X
|
|
||||||
X X
|
|
||||||
XXXXXXX"
|
|
||||||
);
|
|
||||||
|
|
||||||
Paragraph::new(hidden_card)
|
|
||||||
.block(Block::new()
|
|
||||||
.borders(Borders::ALL)
|
|
||||||
.border_type(BorderType::Rounded))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
/// runs the application's main loop until the user quits
|
/// runs the application's main loop until the user quits
|
||||||
@@ -207,12 +114,13 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, frame: &mut Frame) {
|
fn draw(&self, frame: &mut Frame) {
|
||||||
|
let area = frame.area();
|
||||||
let vertical = Layout::vertical([
|
let vertical = Layout::vertical([
|
||||||
Constraint::Length(1),
|
Constraint::Length(1),
|
||||||
Constraint::Min(0),
|
Constraint::Min(0),
|
||||||
Constraint::Length(1),
|
Constraint::Length(1),
|
||||||
]);
|
]);
|
||||||
let [title_bar, main_area, status_bar] = vertical.areas(frame.area());
|
let [title_bar, main_area, status_bar] = vertical.areas(area);
|
||||||
|
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Block::new()
|
Block::new()
|
||||||
@@ -222,7 +130,7 @@ impl App {
|
|||||||
title_bar
|
title_bar
|
||||||
);
|
);
|
||||||
|
|
||||||
let status_bar_info = format!("Cards Per-Draw: {} ---- Times Through Deck: {} ", self.cards.num_cards_turned, self.cards.current_num_passes_through_deck);
|
let status_bar_info = format!("Cards Per-Draw: {} ---- Times Through Deck: {} ---- Press 'h' for Help ", self.cards.num_cards_turned, self.cards.current_num_passes_through_deck);
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Block::new().borders(Borders::TOP).title(status_bar_info),
|
Block::new().borders(Borders::TOP).title(status_bar_info),
|
||||||
status_bar
|
status_bar
|
||||||
@@ -301,7 +209,6 @@ impl App {
|
|||||||
let selected = self.selected_card.is_some() && *c == self.selected_card.unwrap();
|
let selected = self.selected_card.is_some() && *c == self.selected_card.unwrap();
|
||||||
let a_card = match c.visible {
|
let a_card = match c.visible {
|
||||||
true => card_widget(c, is_top_card, highlight, selected),
|
true => card_widget(c, is_top_card, highlight, selected),
|
||||||
//false => turned_over_card(is_top_card),
|
|
||||||
false => card_widget(c, is_top_card, highlight, selected),
|
false => card_widget(c, is_top_card, highlight, selected),
|
||||||
};
|
};
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
@@ -313,6 +220,10 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.show_help {
|
||||||
|
show_help(frame, &area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_events(&mut self) -> io::Result<()> {
|
fn handle_events(&mut self) -> io::Result<()> {
|
||||||
@@ -334,6 +245,7 @@ impl App {
|
|||||||
KeyCode::Char('w') => self.cards.waste_to_deck(),
|
KeyCode::Char('w') => self.cards.waste_to_deck(),
|
||||||
KeyCode::Char('1') => self.cards.num_cards_turned = 1,
|
KeyCode::Char('1') => self.cards.num_cards_turned = 1,
|
||||||
KeyCode::Char('3') => self.cards.num_cards_turned = 3,
|
KeyCode::Char('3') => self.cards.num_cards_turned = 3,
|
||||||
|
KeyCode::Char('h') => self.show_help = !self.show_help, // toggle
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,6 +262,103 @@ fn main() -> io::Result<()> {
|
|||||||
app_result
|
app_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_help(frame: &mut Frame, area: &Rect) {
|
||||||
|
let block = Block::bordered().title("Help");
|
||||||
|
let text =
|
||||||
|
"You are playing \"Legends of Soltar\" - a Klondike thingy
|
||||||
|
Press 'q' to Quit
|
||||||
|
Press '1' or '3' to change the number of cards you draw from the deck
|
||||||
|
Press 'd' to draw from your deck
|
||||||
|
Press 'w' to put the waste pile back into the deck (you can only do this when the waste is empty)";
|
||||||
|
let p = Paragraph::new(text).wrap(Wrap { trim: true });
|
||||||
|
let vertical = Layout::vertical([Constraint::Max(10)]).flex(Flex::Center);
|
||||||
|
let horizontal = Layout::horizontal([Constraint::Percentage(70)]).flex(Flex::Center);
|
||||||
|
let [area] = vertical.areas(*area);
|
||||||
|
let [area] = horizontal.areas(area);
|
||||||
|
frame.render_widget(Clear, area);
|
||||||
|
frame.render_widget(p.block(block), area);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn deck_widget(cards_in_deck: &Vec<card_stuffs::Card>) -> Paragraph<'static> {
|
||||||
|
let card_image = format!(
|
||||||
|
"#############\n\
|
||||||
|
#############\n\
|
||||||
|
### Cards ###\n\
|
||||||
|
### Left ###\n\
|
||||||
|
#############\n\
|
||||||
|
#### {:02} #####\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############", cards_in_deck.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
Paragraph::new(card_image)
|
||||||
|
.block(Block::new()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn partially_covered_card(card: &card_stuffs::Card) -> Paragraph {
|
||||||
|
let card_image = format!(
|
||||||
|
"{value}{suit}", value=card.value, suit=card.suit
|
||||||
|
);
|
||||||
|
let card_style = match card.suit.colour() {
|
||||||
|
card_stuffs::Colour::Black => Style::new().black().bg(Color::White),
|
||||||
|
card_stuffs::Colour::Red => Style::new().red().bg(Color::White),
|
||||||
|
};
|
||||||
|
let borders = Borders::TOP | Borders::LEFT | Borders::BOTTOM;
|
||||||
|
let border_style = Style::new().white().on_black();
|
||||||
|
Paragraph::new(card_image)
|
||||||
|
.style(card_style)
|
||||||
|
.block(Block::new()
|
||||||
|
.style(border_style)
|
||||||
|
.borders(borders)
|
||||||
|
.border_type(BorderType::Rounded))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn facedown_card(top: bool) -> Paragraph<'static> {
|
||||||
|
let hidden_card = format!(
|
||||||
|
"#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############\n\
|
||||||
|
#############"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut borders = Borders::TOP | Borders::LEFT | Borders::RIGHT;
|
||||||
|
if top {
|
||||||
|
borders |= Borders::BOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
Paragraph::new(hidden_card)
|
||||||
|
.block(Block::new()
|
||||||
|
.borders(borders)
|
||||||
|
.border_type(BorderType::Rounded))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_pile() -> Paragraph<'static> {
|
||||||
|
// made using https://www.asciiart.eu/
|
||||||
|
let hidden_card = format!(
|
||||||
|
"
|
||||||
|
XX XX
|
||||||
|
XX XX
|
||||||
|
|
||||||
|
X X
|
||||||
|
X X
|
||||||
|
X X
|
||||||
|
XXXXXXX"
|
||||||
|
);
|
||||||
|
|
||||||
|
Paragraph::new(hidden_card)
|
||||||
|
.block(Block::new()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn card_paragraph(c: &card_stuffs::Card) -> String {
|
fn card_paragraph(c: &card_stuffs::Card) -> String {
|
||||||
|
|||||||
Reference in New Issue
Block a user