use rand::prelude::IteratorRandom; use rand::thread_rng; use serde::{Deserialize, Serialize}; use serde_json::Result; use std::fs; /// A CAH white card #[derive(Serialize, Deserialize)] struct CAHCardWhite { /// Card text text: String, /// ID of the pack it came from pack: u8, } /// A CAH black card #[derive(Serialize, Deserialize)] struct CAHCardBlack { /// Card text text: String, /// Amount of cards to submit for judging pick: u8, /// ID of the pack it came from pack: u8, } /// A CAH pack #[derive(Serialize, Deserialize)] struct CAHCardSet { /// Name of the pack name: String, /// Pack Description description: Option, /// Whether or not this is an official card pack official: bool, /// White card data white: Option>, /// Black card data black: Option>, } /// A struct that represents a player #[derive(Default)] struct CAHPlayer { /// The player's hand white: Vec, /// The player's wins black: Vec, } /// The game master #[derive(Default)] struct CAHGame { /// White draw pile white: Vec, /// Black draw pile black: Vec, /// White discard pile white_discard: Vec, /// Black discard pile black_discard: Vec, /// Indicates game active/game over game_active: bool, /// List of current players players: Vec, // /// Reference to current card czar // czar: &CAHPlayer, /// Black card for the current round current_black: Option, } impl CAHGame { /// Build game decks from input data for game start. /// This should only run once and at startup. fn build_decks(&mut self, cards_json: Vec) { for pack in cards_json { if let Some(white) = pack.white { self.white.extend(white) } if let Some(black) = pack.black { self.black.extend(black) } } } /// Log counts of current drawable cards /// For testing fn deck_counts(&self) { println!( "Deck Counts:\n {} White cards\n {} Black cards", self.white.len(), self.black.len() ); } /// Draw one white card at random from play deck. fn draw_one_white(&mut self) -> Result { let deck = &mut self.white; // this feels sloppy if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { Ok(deck.swap_remove(index)) } else { Ok(CAHCardWhite { text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), pack: 0, }) } } /// Draw one black card at random from play deck. fn draw_one_black(&mut self) -> Result { let deck = &mut self.black; // this feels sloppy if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { Ok(deck.swap_remove(index)) } else { Ok(CAHCardBlack { text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), pick: 0, pack: 0, }) } } /// Deal a black card and use it for the current round /// Returns a reference to the card fn deal_black(&mut self) -> Result<&Option> { self.current_black = Some(self.draw_one_black()?); Ok(&self.current_black) } /// Create a new player and add them to the game. fn create_player(&mut self, player: CAHPlayer) { self.players.push(player); println!("Player Created!"); } } /// Parse json for card data fn load_json(path: &str) -> Result> { let data: String = fs::read_to_string(path).expect("Error reading file"); let jayson: Vec = serde_json::from_str(&data)?; Ok(jayson) } fn main() -> Result<()> { // choose decks let cards_input_path: &str = "data/cah-cards-full.json"; let cards_json: Vec = load_json(cards_input_path)?; // setup let mut cah_game = CAHGame { ..Default::default() }; cah_game.build_decks(cards_json); cah_game.deck_counts(); cah_game.create_player(CAHPlayer { ..Default::default() }); // sloppy ui stuff let div = "--------------------------"; // deal black if let Some(black_card) = cah_game.deal_black()? { println!( "{}\nPick {}\n {}\n{}", div, black_card.pick.to_string(), black_card.text, div, ); } // deal white for i in 1..11 { let card = cah_game.draw_one_white()?; println!("{} {}", i, card.text); } println!("{}", div); cah_game.deck_counts(); // fin Ok(()) }