|
1 /*** Player ****/ |
|
2 |
|
3 use std::collections::VecDeque; |
|
4 use std::mem; |
|
5 |
|
6 use crate::deck::*; |
|
7 use crate::card::*; |
|
8 use crate::row::*; |
|
9 |
|
10 #[derive(Debug)] |
|
11 pub(crate) struct Player { |
|
12 name: String, |
|
13 hand: Deck, |
|
14 pile: VecDeque<Card>, |
|
15 game_point: i32, |
|
16 total_point: i32, |
|
17 rows_busted: i32, |
|
18 wins: i32, |
|
19 } |
|
20 |
|
21 impl Player { |
|
22 pub(crate) fn new(name: String)->Self { |
|
23 debug!("Player {} created", name); |
|
24 Player { |
|
25 name, |
|
26 hand: Deck::new_empty(), |
|
27 pile: VecDeque::new(), |
|
28 game_point: 0, |
|
29 total_point: 0, |
|
30 rows_busted: 0, |
|
31 wins: 0, |
|
32 } |
|
33 } |
|
34 |
|
35 // get one card from th dealer |
|
36 pub(crate) fn get_card( &mut self, card: Card ) { |
|
37 trace!("Player {} got a card {:?}, cards before {}", self.name, &card, self.hand.len()); |
|
38 self.hand.push(card); |
|
39 } |
|
40 |
|
41 // throw a card from hand to the table |
|
42 pub(crate) fn throw_card( &mut self )->Card { |
|
43 if let Some(c) = self.hand.pop() { |
|
44 trace!("Player {} throws a card {:?}", self.name, &c); |
|
45 c |
|
46 } else { |
|
47 panic!("throw_card: Player {} has no card in hand!", self.name); |
|
48 } |
|
49 } |
|
50 |
|
51 // get a busted row of cards |
|
52 pub(crate) fn give_pile( &mut self, cards: VecDeque<Card> ) { |
|
53 for c in cards.into_iter() { |
|
54 self.game_point += c.points as i32; |
|
55 self.pile.push_back(c); |
|
56 } |
|
57 self.rows_busted += 1; |
|
58 trace!("Player {} got busted, count {}", self.name, &self.rows_busted); |
|
59 } |
|
60 |
|
61 pub fn get_name(&self) -> &String { |
|
62 &self.name |
|
63 } |
|
64 |
|
65 // ask the player their score |
|
66 pub(crate) fn get_points( &self ) -> i32 { |
|
67 self.game_point |
|
68 } |
|
69 |
|
70 pub fn get_wins(&self) -> i32 { |
|
71 self.wins |
|
72 } |
|
73 |
|
74 pub(crate) fn inc_wins( &mut self ) { |
|
75 self.wins += 1; |
|
76 } |
|
77 |
|
78 pub fn get_total_points(&self) -> i32 { |
|
79 self.total_point |
|
80 } |
|
81 |
|
82 pub fn get_rows_busted(&self) -> i32 { |
|
83 self.rows_busted |
|
84 } |
|
85 |
|
86 // give back cards from the pile |
|
87 pub(crate) fn get_pile( &mut self ) -> VecDeque<Card> { |
|
88 trace!("Player {} gives back their pile", self.name); |
|
89 mem::take( &mut self.pile ) |
|
90 // same effect: |
|
91 // self.pile.drain(..).collect() |
|
92 |
|
93 // very cumbersome manual fiddling (also reverted...) |
|
94 /* let mut throw: Vec<Card> = Vec::new(); |
|
95 for _i in 0 .. self.pile.len() { |
|
96 throw.push( self.pile.pop().unwrap() ); |
|
97 } |
|
98 throw |
|
99 */ |
|
100 } |
|
101 |
|
102 // I can do this just because I *throw away* c! |
|
103 // doesn't work if I want to use it. |
|
104 /* fn _gimme_pile(self)->Self { |
|
105 for c in &self.pile { |
|
106 println!("Throw {} ", c); |
|
107 } |
|
108 self |
|
109 } |
|
110 */ |
|
111 pub(crate) fn close_round( &mut self ) { |
|
112 if self.hand.len() > 0 { |
|
113 panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len()); |
|
114 } |
|
115 |
|
116 if self.pile.len() > 0 { |
|
117 panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len()); |
|
118 } |
|
119 |
|
120 trace!("Player {} closing round; points={} total so far {}", self.name, self.game_point, self.total_point); |
|
121 self.total_point += self.game_point; |
|
122 self.game_point = 0; |
|
123 } |
|
124 |
|
125 // card too small: pick a row to collect from the rows |
|
126 pub(crate) fn pick_row_for_small_card( &self, rows: &Vec<Row>, playercard: &Card ) -> usize { |
|
127 trace!("Player {} picking a row for small card, card {:?}, rows {:?}", self.name, playercard, rows); |
|
128 |
|
129 // contains the summary point for each row |
|
130 let mut row_points = Vec::with_capacity(5); |
|
131 // the smallest row score |
|
132 let mut smallest = 999; |
|
133 // how many rows have the same smallest score |
|
134 let mut same_point = 0; |
|
135 // the first smallest row_id |
|
136 let mut smallest_rowid = 255; |
|
137 |
|
138 for rowid in 0 .. rows.len() { |
|
139 // DEBUG |
|
140 // println!("pick_row_for_small_card: rowlen {}, rowid {}", rows.len(), rowid); |
|
141 row_points.push( rows[rowid].sum() ); |
|
142 |
|
143 if row_points[rowid] < smallest { |
|
144 // we have a new smallest row |
|
145 smallest = row_points[rowid]; |
|
146 same_point = 0; |
|
147 smallest_rowid = rowid; |
|
148 |
|
149 } else if row_points[rowid] == smallest { |
|
150 // we have another row with same point as smallest |
|
151 same_point += 1; |
|
152 } |
|
153 } |
|
154 |
|
155 if same_point < 1 { |
|
156 // we have one smallest row |
|
157 smallest_rowid.try_into().unwrap() // it's tiny, will fit into u8 |
|
158 |
|
159 } else { |
|
160 // bored, we pick the first now anyway |
|
161 smallest_rowid.try_into().unwrap() |
|
162 } |
|
163 |
|
164 } |
|
165 |
|
166 } |
|
167 |
|
168 /*** PlayerCard ****/ |
|
169 #[derive(Debug)] |
|
170 pub(crate) struct PlayerCard { |
|
171 pub player_id: i32, |
|
172 pub card: Card, |
|
173 } |
|
174 |
|
175 impl PlayerCard { |
|
176 fn _get_player(&self) -> i32 { |
|
177 self.player_id |
|
178 } |
|
179 } |
|
180 |
|
181 impl PartialEq for PlayerCard { |
|
182 fn eq(&self, other: &Self) -> bool { |
|
183 self.card == other.card |
|
184 } |
|
185 } |
|
186 |
|
187 impl PartialOrd for PlayerCard { |
|
188 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
|
189 match self.card.partial_cmp(&other.card) { |
|
190 Some(core::cmp::Ordering::Equal) => {None} |
|
191 ord => return ord, |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 |