src/player.rs
author Peter Gervai <grin@grin.hu>
Tue, 31 Jan 2023 23:25:50 +0100
changeset 4 a2f0cb2b5c13
child 5 0dd7f2c9fd81
permissions -rw-r--r--
Split main into module files.

/*** Player ****/

use std::collections::VecDeque;
use std::mem;

use crate::deck::*;
use crate::card::*;
use crate::row::*;

#[derive(Debug)]
pub(crate) struct Player {
    name: String,
    hand: Deck,
    pile: VecDeque<Card>,
    game_point: i32,
    total_point: i32,
    rows_busted: i32,
    wins: i32,
}

impl Player {
    pub(crate) fn new(name: String)->Self {
        debug!("Player {} created", name);
        Player {
            name,
            hand: Deck::new_empty(),
            pile: VecDeque::new(),
            game_point: 0,
            total_point: 0,
            rows_busted: 0,
            wins: 0,
        }
    }

    // get one card from th dealer
    pub(crate) fn get_card( &mut self, card: Card ) {
        trace!("Player {} got a card {:?}, cards before {}", self.name, &card, self.hand.len());
        self.hand.push(card);
    }

    // throw a card from hand to the table
    pub(crate) fn throw_card( &mut self )->Card {
        if let Some(c) = self.hand.pop() {
            trace!("Player {} throws a card {:?}", self.name, &c);
            c
        } else {
            panic!("throw_card: Player {} has no card in hand!", self.name);
        }
    }

    // get a busted row of cards
    pub(crate) fn give_pile( &mut self, cards: VecDeque<Card> ) {
        for c in cards.into_iter() {
            self.game_point += c.points as i32;
            self.pile.push_back(c);
        }
        self.rows_busted += 1;
        trace!("Player {} got busted, count {}", self.name, &self.rows_busted);
    }

    pub fn get_name(&self) -> &String {
        &self.name
    }

    // ask the player their score
    pub(crate) fn get_points( &self ) -> i32 {
        self.game_point
    }

    pub fn get_wins(&self) -> i32 {
        self.wins
    }

    pub(crate) fn inc_wins( &mut self ) {
        self.wins += 1;
    }

    pub fn get_total_points(&self) -> i32 {
        self.total_point
    }

    pub fn get_rows_busted(&self) -> i32 {
        self.rows_busted
    }

    // give back cards from the pile
    pub(crate) fn get_pile( &mut self ) -> VecDeque<Card> {
        trace!("Player {} gives back their pile", self.name);
        mem::take( &mut self.pile )
        // same effect:
        // self.pile.drain(..).collect()

        // very cumbersome manual fiddling (also reverted...)
/*         let mut throw: Vec<Card> = Vec::new();
        for _i in 0 .. self.pile.len() {
            throw.push( self.pile.pop().unwrap() );
        }
        throw
 */    
    }

    // I can do this just because I *throw away* c!
    // doesn't work if I want to use it.
/*     fn _gimme_pile(self)->Self {
        for c in &self.pile {
            println!("Throw {} ", c);
        }
        self
    }
 */
    pub(crate) fn close_round( &mut self ) {
        if self.hand.len() > 0 {
            panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len());
        }

        if self.pile.len() > 0 {
            panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len());
        }

        trace!("Player {} closing round; points={} total so far {}", self.name, self.game_point, self.total_point);
        self.total_point += self.game_point;
        self.game_point = 0;
    }

    // card too small: pick a row to collect from the rows
    pub(crate) fn pick_row_for_small_card( &self, rows: &Vec<Row>, playercard: &Card ) -> usize {
        trace!("Player {} picking a row for small card, card {:?}, rows {:?}", self.name, playercard, rows);

        // contains the summary point for each row
        let mut row_points = Vec::with_capacity(5);
        // the smallest row score
        let mut smallest = 999;
        // how many rows have the same smallest score
        let mut same_point = 0;
        // the first smallest row_id
        let mut smallest_rowid = 255;

        for rowid in 0 .. rows.len() {
            // DEBUG
            // println!("pick_row_for_small_card: rowlen {}, rowid {}", rows.len(), rowid);
            row_points.push( rows[rowid].sum() );

            if row_points[rowid] < smallest {
                // we have a new smallest row
                smallest = row_points[rowid];
                same_point = 0;
                smallest_rowid = rowid;
            
            } else if row_points[rowid] == smallest {
                // we have another row with same point as smallest
                same_point += 1;
            }
        }

        if same_point < 1 {
            // we have one smallest row
            smallest_rowid.try_into().unwrap()      // it's tiny, will fit into u8
        
        } else {
            // bored, we pick the first now anyway
            smallest_rowid.try_into().unwrap()
        }
        
    }

}

/*** PlayerCard ****/
#[derive(Debug)]
pub(crate) struct PlayerCard {
    pub player_id: i32,
    pub card: Card,
}

impl PlayerCard {
    fn _get_player(&self) -> i32 {
        self.player_id
    }
}

impl PartialEq for PlayerCard {
    fn eq(&self, other: &Self) -> bool {
        self.card == other.card
    }
}

impl PartialOrd for PlayerCard {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        match self.card.partial_cmp(&other.card) {
            Some(core::cmp::Ordering::Equal) => {None}
            ord => return ord,
        }
    }
}