use rand::prelude::*; #[derive(Debug, Clone, Copy)] enum CommunityChest { ToGo, ToJail, Empty, } struct CommunityChestDeck { deck: Vec, current_index: usize, } impl CommunityChestDeck { fn next(&mut self) -> CommunityChest { self.current_index = (self.current_index + 1) % self.deck.len(); self.deck[self.current_index] } } #[derive(Debug, Clone, Copy)] enum Chance { ToGo, ToJail, ToC1, ToE3, ToH2, ToR1, ToNextRailway, ToNextUtility, GoBack3, Empty, } struct ChanceDeck { deck: Vec, current_index: usize, } impl ChanceDeck { fn next(&mut self) -> Chance { self.current_index = (self.current_index + 1) % self.deck.len(); self.deck[self.current_index] } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum TileType { Go, Jail, GoToJail, C1, E3, H2, R1, Railway, Utility, Empty, CommunityChest, Chance, } use TileType::*; struct Board { board: Vec, current_index: usize, } impl Board { fn next(&mut self) -> TileType { self.current_index = (self.current_index + 1) % self.board.len(); self.board[self.current_index] } fn prev(&mut self) -> TileType { self.current_index = ((self.current_index as i32 - 1) % self.board.len() as i32) as usize; self.board[self.current_index] } } struct DoubleDice { sides: u32, rng: ThreadRng, } impl DoubleDice { // Need to know each specific throw because we need to keep track of the doubles fn throw(&mut self) -> (u32, u32) { let dice1 = self.rng.gen_range(1..=self.sides); let dice2 = self.rng.gen_range(1..=self.sides); (dice1, dice2) } } enum ThrowResult { ToJail, Moves(u32), } fn handle_dice(dice: &mut DoubleDice, past_throws: &mut [(u32, u32)]) -> ThrowResult { let dice_throw = dice.throw(); if past_throws[0] == past_throws[1] && past_throws[1] == dice_throw { past_throws[0] = (0, 0); past_throws[1] = (0, 0); ThrowResult::ToJail } else { past_throws[0] = past_throws[1]; past_throws[1] = dice_throw; ThrowResult::Moves(dice_throw.0 + dice_throw.1) } } fn main() { println!("Hello, this is Patrick!"); let mut rng = thread_rng(); // First create card decks, board and dice let mut community_chest_cards = vec![ CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::Empty, CommunityChest::ToGo, CommunityChest::ToJail, ]; community_chest_cards.shuffle(&mut rng); let mut chance_cards = vec![ Chance::Empty, Chance::Empty, Chance::Empty, Chance::Empty, Chance::Empty, Chance::Empty, Chance::ToGo, Chance::ToJail, Chance::ToC1, Chance::ToE3, Chance::ToH2, Chance::ToR1, Chance::ToNextRailway, Chance::ToNextRailway, Chance::ToNextUtility, Chance::GoBack3, ]; chance_cards.shuffle(&mut rng); let board_tiles = vec![ Go, Empty, CommunityChest, Empty, Empty, R1, Empty, Chance, Empty, Empty, Jail, C1, Utility, Empty, Empty, Railway, Empty, CommunityChest, Empty, Empty, Empty, Empty, Chance, Empty, E3, Railway, Empty, Empty, Utility, Empty, GoToJail, Empty, Empty, CommunityChest, Empty, Railway, Chance, Empty, Empty, H2, ]; let mut cc_deck = CommunityChestDeck { deck: community_chest_cards, current_index: 0, }; let mut chance_deck = ChanceDeck { deck: chance_cards, current_index: 0, }; let mut board = Board { board: board_tiles, current_index: 0, }; let mut dice = DoubleDice { sides: 4, rng }; let mut square_popularity = vec![0; board.board.len()]; let mut dice_throws = [(0, 0), (0, 0)]; for _ in 0..2000000 { match handle_dice(&mut dice, &mut dice_throws) { ThrowResult::ToJail => { board.current_index = 10; } ThrowResult::Moves(n) => { let mut next_tile = Empty; for _ in 0..n { next_tile = board.next(); } match next_tile { GoToJail => { board.current_index = 10; } CommunityChest => { let card_drawn = cc_deck.next(); match card_drawn { CommunityChest::ToGo => { board.current_index = 0; } CommunityChest::ToJail => { board.current_index = 10; } _ => {} } } Chance => { let card_drawn = chance_deck.next(); match card_drawn { Chance::ToJail => { board.current_index = 10; } Chance::ToGo => { board.current_index = 0; } Chance::Empty => {} Chance::GoBack3 => { for _ in 0..3 { _ = board.prev() } } Chance::ToC1 => while board.next() != TileType::C1 {}, Chance::ToE3 => while board.next() != TileType::E3 {}, Chance::ToH2 => while board.next() != TileType::H2 {}, Chance::ToNextUtility => while board.next() != TileType::Utility {}, Chance::ToR1 => while board.next() != TileType::R1 {}, Chance::ToNextRailway => { let mut next_tile = board.next(); while next_tile != TileType::R1 && next_tile != TileType::Railway { next_tile = board.next(); } } } } _ => {} } } } square_popularity[board.current_index] += 1; } let mut squares_sorted: Vec<(usize, u32)> = square_popularity.into_iter().enumerate().collect(); squares_sorted.sort_by(|(_, a), (_, b)| a.cmp(b)); println!("Square popularity: {:?}", squares_sorted); }