Exchanges, initial cards

This commit is contained in:
Dane Johnson 2022-05-25 18:17:00 -05:00
parent cab89f5d64
commit 7f83f2f8cb

View File

@ -246,7 +246,148 @@ impl Game {
self.turn = next; self.turn = next;
} }
} }
}
pub struct PublicGame {
pub players: Vec<PublicPlayer>,
pub discard: Vec<Card>,
}
impl From<Game> 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<Player> 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<usize>,
}
#[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<mpsc::Sender<Message>>,
rxs: Vec<mpsc::Receiver<Message>>,
}
impl Channels {
pub fn add_channel(&mut self, tx: mpsc::Sender<Message>, rx: mpsc::Receiver<Message>) {
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<Message> {
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<Move> {
let msg = self.recv(id);
match msg {
Message::Move(move_) => Ok(move_),
_ => Err("Expected move"),
}
}
pub fn recv_discard(&self, id: usize) -> CoupResult<Card> {
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<Card> {
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<()> { fn player_lose_influence(&mut self, id: usize, channels: &Channels) -> CoupResult<()> {
channels.send(id, Message::LoseInfluence); channels.send(id, Message::LoseInfluence);
let card = channels.recv_discard(id)?; let card = channels.recv_discard(id)?;
@ -261,7 +402,6 @@ impl Game {
} }
pub fn action(&mut self, channels: &Channels) -> CoupResult<Phase> { pub fn action(&mut self, channels: &Channels) -> CoupResult<Phase> {
channels.broadcast(Message::Turn(self.turn));
let move_ = channels.recv_move(self.turn)?; let move_ = channels.recv_move(self.turn)?;
if move_.action.is_targeted() && move_.target.is_none() { if move_.action.is_targeted() && move_.target.is_none() {
Err("Targeted action with no target") Err("Targeted action with no target")
@ -415,6 +555,7 @@ impl Game {
Tax => self.players[self.turn].coins += 3, Tax => self.players[self.turn].coins += 3,
Exchange => { Exchange => {
let drawn = vec![self.deck.pop().unwrap(), self.deck.pop().unwrap()]; 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 hand = self.players[self.turn].cards.clone();
let mut choices = [drawn, hand].concat(); let mut choices = [drawn, hand].concat();
let mut discarded = [Ambassador; 2]; let mut discarded = [Ambassador; 2];
@ -446,111 +587,15 @@ impl Game {
} }
} }
#[derive(PartialEq, Debug, Clone, Copy)] fn card_arr(cards: &[Card]) -> [Card; 2] {
pub struct Move { if cards.len() < 2 {
pub action: Action, panic!("Not enough cards");
pub target: Option<usize>,
}
#[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<mpsc::Sender<Message>>,
rxs: Vec<mpsc::Receiver<Message>>,
}
impl Channels {
pub fn add_channel(&mut self, tx: mpsc::Sender<Message>, rx: mpsc::Receiver<Message>) {
self.txs.push(tx);
self.rxs.push(rx);
} }
pub fn send(&self, id: usize, msg: Message) { let mut arr = [Duke, Duke];
self.txs[id].send(msg).unwrap(); for i in 0..2 {
} arr[i] = cards[i];
pub fn recv(&self, id: usize) -> Message {
self.rxs[id].recv().unwrap()
}
pub fn try_recv(&self, id: usize) -> Option<Message> {
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<Move> {
let msg = self.recv(id);
match msg {
Message::Move(move_) => Ok(move_),
_ => Err("Expected move"),
}
}
pub fn recv_discard(&self, id: usize) -> CoupResult<Card> {
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<Card> {
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
} }
arr
} }