use anyhow::Result; use rand::prelude::IteratorRandom; use rand::thread_rng; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; /// User pub struct User { pub name: String, pub addr: SocketAddr, } /// New game request structure #[derive(Debug, Deserialize)] pub struct NewGameRequest { /// Game name pub name: String, /// Game host pub host: CAHPlayer, /// Chosen packs pub packs: Vec, } /// Game join request structure pub struct GameJoinRequest { /// Game id pub id: u8, // increase later /// Game password pub password: Option, /// Player info pub player: CAHPlayer, } /// A CAH white card #[derive(Debug, Serialize, Deserialize)] pub struct CAHCardWhite { /// Card text pub text: String, /// ID of the pack it came from pack: u8, } /// A CAH black card #[derive(Debug, Serialize, Deserialize)] pub struct CAHCardBlack { /// Card text pub text: String, /// Amount of cards to submit for judging pick: u8, /// ID of the pack it came from pack: u8, } /// A CAH pack #[derive(Debug, Serialize, Deserialize)] pub 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>, } /// Player roles #[derive(Debug, Deserialize)] pub enum PlayerRole { /// Player is host Host, /// Player is a player in a game where another player is host Player, /// Player is just spectating Spectator, } /// A struct that represents a player #[derive(Debug, Deserialize)] pub struct CAHPlayer { /// Player's username pub name: String, /// This player's role pub role: PlayerRole, /// The player's hand pub white: Vec, /// The player's wins pub black: Vec, } /// The game master #[derive(Default)] pub struct CAHGame { /// The name of the game pub name: String, /// White draw pile pub white: Vec, /// Black draw pile pub black: Vec, /// White discard pile pub white_discard: Vec, /// Black discard pile pub black_discard: Vec, /// Indicates game active/game over pub game_active: bool, /// List of current players pub players: Vec, // /// Reference to current card czar // czar: &CAHPlayer, /// Black card for the current round pub 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) -> Result<()> { 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) } } Ok(()) } pub fn new(request: NewGameRequest) -> Result { let mut game = CAHGame { ..Default::default() }; tracing::debug!("Creating game {}", &request.name); game.name = request.name; // game.build_decks(request.packs)?; game.create_player(request.host)?; game.deal_black()?; Ok(game) } // pub fn join(request:GameJoinRequest) /// Log counts of current drawable cards /// For testing pub fn deck_counts(&self) { tracing::debug!( "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 fn deal_black(&mut self) -> Result<()> { self.current_black = Some(self.draw_one_black()?); Ok(()) } /// Create a new player and add them to the game. pub fn create_player(&mut self, mut player: CAHPlayer) -> Result<()> { tracing::debug!("Creating player {} as {:?}", &player.name, &player.role); let mut hand_buf = vec![]; for _ in 0..10 { hand_buf.push(self.draw_one_white()?); } tracing::debug!("Dealing hand to {}", &player.name); player.white.extend(hand_buf); self.players.push(player); Ok(()) } pub fn game_start(&mut self) -> Result<()> { self.game_active = true; tracing::debug!("Game Active!"); if let Some(black) = &self.current_black { tracing::debug!("{}", black.text); } else { tracing::debug!("YOU DONE FUCKED UP (no current black card)"); } Ok(()) } }