use game::round::Round;
use game::player::Player;
use cards::deck::Deck;
use cards::types::{Rank, Suit};
use cards::card::{PlayerCard, Card};
use game::player_move::{Move, TrickType, build_move};
#[derive(Clone, Debug)]
pub struct GameDefinition{
pub players: Vec<Player>,
pub round: Round,
pub winners: Vec<u64>,
pub reversed: bool
}
pub struct Game {
players: Vec<Player>,
round: Round,
winners: Vec<u64>,
reversed: bool
}
impl Game{
pub fn setup(player_ids:Vec<u64>, num_decks:usize) -> Result<GameDefinition, &'static str>{
let mut decks = vec!();
while decks.len() < num_decks {
decks.push(Deck::new());
}
let mut deck = Deck::combine(decks);
deck.shuffle();
let player_count = player_ids.len();
let dealt_cards = deck.deal(player_count);
let mut cards_iter = dealt_cards.iter();
let mut players = vec!();
for id in player_ids.iter() {
let player = Player::new(*id);
let hand = cards_iter.next().unwrap();
players.push(player.set_hand(hand.clone()));
}
let next_player = Game::get_next(&players).unwrap().get_id();
Ok(
GameDefinition{
players: players,
round: Game::get_empty_round(player_ids.clone(), next_player),
winners: vec!(),
reversed: false
}
)
}
pub fn load(game_definition: GameDefinition) -> Result<Game, &'static str>{
Ok(
Game{
players: game_definition.players,
round: game_definition.round,
winners: game_definition.winners,
reversed: game_definition.reversed
}
)
}
pub fn player_move(&self, player_id:u64, cards:Vec<PlayerCard>) -> Result<GameDefinition, &'static str> {
let p_move = build_move(cards.clone());
if p_move == None {
return Err("Invalid move!");
}
let current_player = self.get_current_player(player_id);
if current_player == None {
return Err("Invalid player!");
}
let mut current_player = current_player.unwrap();
if !self.player_has_card(¤t_player, cards.clone()) {
return Err("Cannot play cards you do not have");
}
let mut players = self.players.clone();
let valid_move;
let mut round = match self.round.play(player_id, p_move.unwrap()){
Ok(r) => {
valid_move = true;
current_player = current_player.remove(&cards);
players = self.replace_current_player(¤t_player);
let player_ids = self.get_players_for_next_round(&players);
r.update_players(player_ids)
},
Err(r) => {
valid_move = false;
r
}
};
let mut reversed = self.reversed;
if valid_move {
match p_move {
Some(Move::FiveCardTrick(t)) => match t.trick_type {
TrickType::FourOfAKind
| TrickType::FiveOfAKind => {
round = round.reverse_last_move();
players = players.iter().map(|ref p|{ p.reverse_hand() }).collect::<Vec<Player>>();
reversed = !self.reversed;
},
_ => ()
},
_ => ()
}
}
if round.export().players.len() < self.round.export().players.len(){
round = round.set_pass_count(-1);
}
let winners = self.get_winners(¤t_player);
let game_def = GameDefinition{
players: players.clone(),
round: round,
winners: winners,
reversed: reversed
};
if valid_move {
Ok(game_def)
} else {
Err("move was invalid")
}
}
pub fn get_player(&self, id: u64) -> Option<Player> {
self.get_current_player(id)
}
pub fn get_next_player(&self) -> Option<Player> {
let id = match self.round.has_started() {
true => self.round.get_next_player(),
false => match Game::get_next(&self.players) {
Some(player) => player.get_id(),
_ => self.round.get_next_player()
}
};
self.get_player(id)
}
fn get_next(players: &Vec<Player>) -> Option<Player> {
let three_of_clubs = card!(Three, Clubs);
for player in players {
if player.get_hand().contains(&three_of_clubs){
return Some(player.clone());
}
}
None
}
fn get_empty_round(player_ids:Vec<u64>, next:u64) -> Round {
Round::new(player_ids, next, Move::Pass, 0, true)
}
fn get_winners(&self, current_player: &Player) -> Vec<u64> {
let mut winners = self.winners.clone();
if current_player.get_hand().len() == 0 {
winners.push(current_player.get_id());
}
winners
}
fn get_current_player(&self, player_id:u64) -> Option<Player> {
for player in &self.players {
if player.get_id() == player_id {
return Some(player.clone());
}
}
None
}
fn replace_current_player(&self, current_player: &Player) -> Vec<Player> {
let mut players = vec!();
for player in &self.players{
if player.get_id() == current_player.get_id(){
players.push(current_player.clone());
}else{
players.push(player.clone());
}
}
players
}
fn get_players_for_next_round(&self, players: &Vec<Player>) -> Vec<u64> {
players.iter()
.filter(|player|{ player.get_hand().len() > 0 })
.map(|player|{ player.get_id() }).collect()
}
fn player_has_card(&self, player:&Player, cards:Vec<PlayerCard>) -> bool {
for card in &cards {
match *card {
PlayerCard::Card(_) => {
let hand = player.get_hand();
let reversed_hand = player.reverse_hand().get_hand();
if !hand.contains(&card) && !reversed_hand.contains(&card){
return false;
}
},
PlayerCard::Wildcard(_) => {
},
PlayerCard::Joker(_) => { panic!("Joker is not a valid move - do you mean Wildcard?"); }
}
}
true
}
}