From 7f83f2f8cb712a408cc838b8b4375a2e51502330 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Wed, 25 May 2022 18:17:00 -0500 Subject: [PATCH] Exchanges, initial cards --- src/lib.rs | 253 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 104 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d43c8c2..193686b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -246,7 +246,148 @@ impl Game { self.turn = next; } } +} +pub struct PublicGame { + pub players: Vec, + pub discard: Vec, +} + +impl From for PublicGame { + fn from(game: Game) -> Self { + let players = game.players.into_iter().map(PublicPlayer::from).collect(); + let discard = game.discard; + PublicGame { players, discard } + } +} + +pub struct PublicPlayer { + pub cards: usize, + pub coins: u8, +} + +impl From for PublicPlayer { + fn from(player: Player) -> Self { + let cards = player.cards.len(); + let coins = player.coins; + PublicPlayer { cards, coins } + } +} + +#[derive(PartialEq, Debug, Clone, Copy)] +pub struct Move { + pub action: Action, + pub target: Option, +} + +#[derive(PartialEq, Debug, Clone, Copy)] +pub struct Block { + pub blocker: usize, + pub card: Card, +} + +/// Phase we should move to. +/// +/// Coup turns have 5 phases, depending on what actions are taken each phase +/// some phases might be skipped. +#[derive(PartialEq, Debug)] +pub enum Phase { + ActionChallenge(Move), + Block(Move), + BlockChallenge(Move, Block), + Resolution(Move), + Done, +} + +use std::sync::mpsc; + +#[derive(Default)] +pub struct Channels { + txs: Vec>, + rxs: Vec>, +} + +impl Channels { + pub fn add_channel(&mut self, tx: mpsc::Sender, rx: mpsc::Receiver) { + self.txs.push(tx); + self.rxs.push(rx); + } + pub fn send(&self, id: usize, msg: Message) { + self.txs[id].send(msg).unwrap(); + } + pub fn recv(&self, id: usize) -> Message { + self.rxs[id].recv().unwrap() + } + pub fn try_recv(&self, id: usize) -> Option { + self.rxs[id].try_recv().ok() + } + pub fn broadcast(&self, msg: Message) { + for id in 0..self.rxs.len() { + self.send(id, msg); + } + } + pub fn recv_move(&self, id: usize) -> CoupResult { + let msg = self.recv(id); + match msg { + Message::Move(move_) => Ok(move_), + _ => Err("Expected move"), + } + } + pub fn recv_discard(&self, id: usize) -> CoupResult { + let msg = self.recv(id); + match msg { + Message::Discard(card) => Ok(card), + _ => Err("Expected discard") + } + } + pub fn try_recv_challenge(&self, id: usize) -> Option<()> { + let msg = self.try_recv(id); + match msg { + Some(Message::Challenge) => Some(()), + _ => None, + } + } + pub fn try_recv_block(&self, id: usize) -> Option { + let msg = self.try_recv(id); + match msg { + Some(Message::Block(card)) => Some(card), + _ => None, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Message { + InitialDraw([Card; 2]), + Exchange([Card; 2]), + Turn(usize), + LoseInfluence, + Move(Move), + Challenge, + Block(Card), + Discard(Card), +} + +use std::time::{ Instant, Duration }; +const WAIT_TIME: Duration = Duration::from_secs(1); +struct Timer { + start: Instant, +} +impl Timer { + fn start() -> Self { + Timer { start: Instant::now() } + } + fn is_timeout(&self) -> bool { + Instant::now() > self.start + WAIT_TIME + } +} + +impl Game { + pub fn initial_hand(&self, channels: &Channels) { + for (id, player) in self.players.iter().enumerate() { + channels.send(id, Message::InitialDraw(card_arr(&player.cards))); + } + } fn player_lose_influence(&mut self, id: usize, channels: &Channels) -> CoupResult<()> { channels.send(id, Message::LoseInfluence); let card = channels.recv_discard(id)?; @@ -261,7 +402,6 @@ impl Game { } pub fn action(&mut self, channels: &Channels) -> CoupResult { - channels.broadcast(Message::Turn(self.turn)); let move_ = channels.recv_move(self.turn)?; if move_.action.is_targeted() && move_.target.is_none() { Err("Targeted action with no target") @@ -415,6 +555,7 @@ impl Game { Tax => self.players[self.turn].coins += 3, Exchange => { let drawn = vec![self.deck.pop().unwrap(), self.deck.pop().unwrap()]; + channels.send(self.turn, Message::Exchange(card_arr(&drawn))); let hand = self.players[self.turn].cards.clone(); let mut choices = [drawn, hand].concat(); let mut discarded = [Ambassador; 2]; @@ -446,111 +587,15 @@ impl Game { } } -#[derive(PartialEq, Debug, Clone, Copy)] -pub struct Move { - pub action: Action, - pub target: Option, -} - -#[derive(PartialEq, Debug, Clone, Copy)] -pub struct Block { - pub blocker: usize, - pub card: Card, -} - -/// Phase we should move to. -/// -/// Coup turns have 5 phases, depending on what actions are taken each phase -/// some phases might be skipped. -#[derive(PartialEq, Debug)] -pub enum Phase { - ActionChallenge(Move), - Block(Move), - BlockChallenge(Move, Block), - Resolution(Move), - Done, -} - -use std::sync::mpsc; - - -#[derive(Default)] -pub struct Channels { - txs: Vec>, - rxs: Vec>, -} - -impl Channels { - pub fn add_channel(&mut self, tx: mpsc::Sender, rx: mpsc::Receiver) { - self.txs.push(tx); - self.rxs.push(rx); +fn card_arr(cards: &[Card]) -> [Card; 2] { + if cards.len() < 2 { + panic!("Not enough cards"); } - pub fn send(&self, id: usize, msg: Message) { - self.txs[id].send(msg).unwrap(); - } - pub fn recv(&self, id: usize) -> Message { - self.rxs[id].recv().unwrap() - } - pub fn try_recv(&self, id: usize) -> Option { - self.rxs[id].try_recv().ok() - } - pub fn broadcast(&self, msg: Message) { - for id in 0..self.rxs.len() { - self.send(id, msg); - } - } - pub fn recv_move(&self, id: usize) -> CoupResult { - let msg = self.recv(id); - match msg { - Message::Move(move_) => Ok(move_), - _ => Err("Expected move"), - } - } - pub fn recv_discard(&self, id: usize) -> CoupResult { - let msg = self.recv(id); - match msg { - Message::Discard(card) => Ok(card), - _ => Err("Expected discard") - } - } - pub fn try_recv_challenge(&self, id: usize) -> Option<()> { - let msg = self.try_recv(id); - match msg { - Some(Message::Challenge) => Some(()), - _ => None, - } - } - pub fn try_recv_block(&self, id: usize) -> Option { - let msg = self.try_recv(id); - match msg { - Some(Message::Block(card)) => Some(card), - _ => None, - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Message { - Turn(usize), - LoseInfluence, - Move(Move), - Challenge, - Block(Card), - Discard(Card), -} - -use std::time::{ Instant, Duration }; -const WAIT_TIME: Duration = Duration::from_secs(1); -struct Timer { - start: Instant, -} -impl Timer { - fn start() -> Self { - Timer { start: Instant::now() } - } - fn is_timeout(&self) -> bool { - Instant::now() > self.start + WAIT_TIME + let mut arr = [Duke, Duke]; + for i in 0..2 { + arr[i] = cards[i]; } + arr }