5
|
1 |
/// This is the implementation of a Player. |
4
|
2 |
|
|
3 |
use std::collections::VecDeque; |
5
|
4 |
// We use this to move variables out of a Vec with ownership. |
4
|
5 |
use std::mem; |
|
6 |
|
|
7 |
use crate::deck::*; |
|
8 |
use crate::card::*; |
|
9 |
use crate::row::*; |
|
10 |
|
|
11 |
#[derive(Debug)] |
5
|
12 |
/// A `Player` is a person in the game. |
|
13 |
/// # Structure members |
|
14 |
/// * `name` - the name of the Player |
|
15 |
/// * `hand` - the cards in the hand of Player, stored as a [`Deck`], so, for example, it could be shuffled or sorted. |
|
16 |
/// * `pile` - the pile of busted [`Row`] [`Card`]s, counted at the end of the round. |
|
17 |
/// * `game_point` - points in the current game round |
|
18 |
/// * `total_point` - points in all the games total |
|
19 |
/// * `rows_busted` - just counting how many rows the player have collected |
|
20 |
/// * `wins` - how many games have the Player won |
4
|
21 |
pub(crate) struct Player { |
|
22 |
name: String, |
|
23 |
hand: Deck, |
|
24 |
pile: VecDeque<Card>, |
|
25 |
game_point: i32, |
|
26 |
total_point: i32, |
|
27 |
rows_busted: i32, |
|
28 |
wins: i32, |
|
29 |
} |
|
30 |
|
|
31 |
impl Player { |
5
|
32 |
/// Creates a new [`Player`] with a given `name`. |
4
|
33 |
pub(crate) fn new(name: String)->Self { |
|
34 |
debug!("Player {} created", name); |
|
35 |
Player { |
|
36 |
name, |
|
37 |
hand: Deck::new_empty(), |
|
38 |
pile: VecDeque::new(), |
|
39 |
game_point: 0, |
|
40 |
total_point: 0, |
|
41 |
rows_busted: 0, |
|
42 |
wins: 0, |
|
43 |
} |
|
44 |
} |
|
45 |
|
5
|
46 |
/// get one card from the dealer |
4
|
47 |
pub(crate) fn get_card( &mut self, card: Card ) { |
|
48 |
trace!("Player {} got a card {:?}, cards before {}", self.name, &card, self.hand.len()); |
|
49 |
self.hand.push(card); |
|
50 |
} |
|
51 |
|
5
|
52 |
/// throw a card from hand to the table |
4
|
53 |
pub(crate) fn throw_card( &mut self )->Card { |
|
54 |
if let Some(c) = self.hand.pop() { |
|
55 |
trace!("Player {} throws a card {:?}", self.name, &c); |
|
56 |
c |
|
57 |
} else { |
|
58 |
panic!("throw_card: Player {} has no card in hand!", self.name); |
|
59 |
} |
|
60 |
} |
|
61 |
|
5
|
62 |
/// get a busted row of cards |
4
|
63 |
pub(crate) fn give_pile( &mut self, cards: VecDeque<Card> ) { |
|
64 |
for c in cards.into_iter() { |
|
65 |
self.game_point += c.points as i32; |
|
66 |
self.pile.push_back(c); |
|
67 |
} |
|
68 |
self.rows_busted += 1; |
|
69 |
trace!("Player {} got busted, count {}", self.name, &self.rows_busted); |
|
70 |
} |
|
71 |
|
5
|
72 |
/// Get the name of the Player |
4
|
73 |
pub fn get_name(&self) -> &String { |
|
74 |
&self.name |
|
75 |
} |
|
76 |
|
5
|
77 |
/// ask the player their score |
4
|
78 |
pub(crate) fn get_points( &self ) -> i32 { |
|
79 |
self.game_point |
|
80 |
} |
|
81 |
|
5
|
82 |
/// Get the number of games won |
4
|
83 |
pub fn get_wins(&self) -> i32 { |
|
84 |
self.wins |
|
85 |
} |
|
86 |
|
5
|
87 |
/// Player won this game, increment counter |
4
|
88 |
pub(crate) fn inc_wins( &mut self ) { |
|
89 |
self.wins += 1; |
|
90 |
} |
|
91 |
|
5
|
92 |
/// Get total points of all games |
4
|
93 |
pub fn get_total_points(&self) -> i32 { |
|
94 |
self.total_point |
|
95 |
} |
|
96 |
|
5
|
97 |
/// Get the number of total busted rows |
4
|
98 |
pub fn get_rows_busted(&self) -> i32 { |
|
99 |
self.rows_busted |
|
100 |
} |
|
101 |
|
5
|
102 |
/// give back cards from the player's pile ino the Deck |
4
|
103 |
pub(crate) fn get_pile( &mut self ) -> VecDeque<Card> { |
|
104 |
trace!("Player {} gives back their pile", self.name); |
5
|
105 |
// Here we take the ownership of the `pile` VecDeque<Card> structure, |
|
106 |
// and replace it with "the default" (an empty VecDeque); we can |
|
107 |
// return it now without taking a mutable borrow of `self`. |
4
|
108 |
mem::take( &mut self.pile ) |
5
|
109 |
|
|
110 |
// same effect (`drain()` also transfers ownership): |
4
|
111 |
// self.pile.drain(..).collect() |
|
112 |
|
5
|
113 |
// very cumbersome manual fiddling (also in wrong/reverted order...) |
|
114 |
/* let mut throw: Vec<Card> = Vec::new(); |
4
|
115 |
for _i in 0 .. self.pile.len() { |
|
116 |
throw.push( self.pile.pop().unwrap() ); |
|
117 |
} |
|
118 |
throw |
|
119 |
*/ |
|
120 |
} |
|
121 |
|
|
122 |
// I can do this just because I *throw away* c! |
5
|
123 |
// Doesn't work if I want to use/return it. |
4
|
124 |
/* fn _gimme_pile(self)->Self { |
|
125 |
for c in &self.pile { |
|
126 |
println!("Throw {} ", c); |
|
127 |
} |
|
128 |
self |
|
129 |
} |
|
130 |
*/ |
5
|
131 |
/// End of round, "close" the Player and verify that we did all right. |
|
132 |
/// These ought to be `assert()` calls, but... same thing. |
4
|
133 |
pub(crate) fn close_round( &mut self ) { |
|
134 |
if self.hand.len() > 0 { |
|
135 |
panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len()); |
|
136 |
} |
|
137 |
|
|
138 |
if self.pile.len() > 0 { |
|
139 |
panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len()); |
|
140 |
} |
|
141 |
|
|
142 |
trace!("Player {} closing round; points={} total so far {}", self.name, self.game_point, self.total_point); |
|
143 |
self.total_point += self.game_point; |
|
144 |
self.game_point = 0; |
|
145 |
} |
|
146 |
|
5
|
147 |
/// Card too small: pick a row to collect from the rows. |
|
148 |
/// It selects the first row with the lowest `points`. |
|
149 |
/// |
|
150 |
/// # Arguments |
|
151 |
/// * `rows` - A `Vec`tor of [`Row`]s to pick from |
|
152 |
/// * `playercard` - The actual card the player just thrown, which could be used in decision (but it isn't now) |
4
|
153 |
pub(crate) fn pick_row_for_small_card( &self, rows: &Vec<Row>, playercard: &Card ) -> usize { |
|
154 |
trace!("Player {} picking a row for small card, card {:?}, rows {:?}", self.name, playercard, rows); |
|
155 |
|
|
156 |
// contains the summary point for each row |
|
157 |
let mut row_points = Vec::with_capacity(5); |
5
|
158 |
// the smallest row score (we start by something larger than anything possible) |
4
|
159 |
let mut smallest = 999; |
|
160 |
// how many rows have the same smallest score |
|
161 |
let mut same_point = 0; |
5
|
162 |
// the first smallest row_id (start by larger than max) |
4
|
163 |
let mut smallest_rowid = 255; |
|
164 |
|
|
165 |
for rowid in 0 .. rows.len() { |
5
|
166 |
// debug!("pick_row_for_small_card: rowlen {}, rowid {}", rows.len(), rowid); |
|
167 |
// As Row to calculate the summary points for itself and store it in a Vec |
4
|
168 |
row_points.push( rows[rowid].sum() ); |
|
169 |
|
|
170 |
if row_points[rowid] < smallest { |
|
171 |
// we have a new smallest row |
|
172 |
smallest = row_points[rowid]; |
|
173 |
same_point = 0; |
|
174 |
smallest_rowid = rowid; |
|
175 |
|
|
176 |
} else if row_points[rowid] == smallest { |
|
177 |
// we have another row with same point as smallest |
|
178 |
same_point += 1; |
|
179 |
} |
|
180 |
} |
|
181 |
|
|
182 |
if same_point < 1 { |
|
183 |
// we have one smallest row |
5
|
184 |
smallest_rowid.try_into().unwrap() // it's tiny, will fit into u8, so unwrap() is safe |
4
|
185 |
|
|
186 |
} else { |
5
|
187 |
// bored, we pick the first now anyway; this could be smarter, but possibly |
|
188 |
// it would require peeking at other rows and the thrown cards of others. |
4
|
189 |
smallest_rowid.try_into().unwrap() |
|
190 |
} |
|
191 |
|
|
192 |
} |
|
193 |
|
|
194 |
} |
|
195 |
|
5
|
196 |
/// `PlayerCard` is a [`Card`] associated with a Player. |
4
|
197 |
#[derive(Debug)] |
|
198 |
pub(crate) struct PlayerCard { |
|
199 |
pub player_id: i32, |
|
200 |
pub card: Card, |
|
201 |
} |
|
202 |
|
|
203 |
impl PlayerCard { |
5
|
204 |
/// It isn't used because I was tired fighting with the borrow checker ;-) |
4
|
205 |
fn _get_player(&self) -> i32 { |
|
206 |
self.player_id |
|
207 |
} |
|
208 |
} |
|
209 |
|
5
|
210 |
/// We use this to sort the [`Card`]s, using its own knowledge about equality. |
4
|
211 |
impl PartialEq for PlayerCard { |
|
212 |
fn eq(&self, other: &Self) -> bool { |
|
213 |
self.card == other.card |
|
214 |
} |
|
215 |
} |
|
216 |
|
5
|
217 |
/// We use this to sort the [`Card`]s, using its own knowledge about ordering. |
4
|
218 |
impl PartialOrd for PlayerCard { |
|
219 |
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
|
220 |
match self.card.partial_cmp(&other.card) { |
|
221 |
Some(core::cmp::Ordering::Equal) => {None} |
|
222 |
ord => return ord, |
|
223 |
} |
|
224 |
} |
|
225 |
} |
|
226 |
|
|
227 |
|