Exchanges, initial cards
This commit is contained in:
parent
cab89f5d64
commit
7f83f2f8cb
253
src/lib.rs
253
src/lib.rs
@ -246,7 +246,148 @@ impl Game {
|
||||
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<()> {
|
||||
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<Phase> {
|
||||
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<usize>,
|
||||
fn card_arr(cards: &[Card]) -> [Card; 2] {
|
||||
if cards.len() < 2 {
|
||||
panic!("Not enough cards");
|
||||
}
|
||||
|
||||
#[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 {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user