76 fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
87 fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
77 self.value.cmp(&other.value) |
88 self.value.cmp(&other.value) |
78 } |
89 } |
79 } |
90 } |
80 |
91 |
81 |
92 /*** Deck ****/ |
82 #[derive(Debug)] |
93 #[derive(Debug)] |
83 struct Deck { |
94 struct Deck { |
84 content: VecDeque<Card>, |
95 content: VecDeque<Card>, |
85 } |
96 } |
86 |
97 |
87 impl Deck { |
98 impl Deck { |
88 fn new_empty() -> Self { |
99 fn new_empty() -> Self { |
|
100 debug!("Empty deck generated"); |
89 Deck { |
101 Deck { |
90 content: VecDeque::new(), |
102 content: VecDeque::new(), |
91 } |
103 } |
92 } |
104 } |
93 |
105 |
94 fn new() -> Self { |
106 fn new() -> Self { |
95 let content = (1..104).into_iter().map( |n| Card::new(n) ).collect(); |
107 debug!("Full deck generated"); |
|
108 let content = (1..=104).into_iter().map( |n| Card::new(n) ).collect(); |
96 Deck { |
109 Deck { |
97 content, |
110 content, |
98 } |
111 } |
99 } |
112 } |
100 |
113 |
101 fn shuffle( &mut self ) { |
114 fn shuffle( &mut self ) { |
102 let mut rng = rand::thread_rng(); |
115 let mut rng = rand::thread_rng(); |
103 |
116 |
|
117 trace!("Deck before shuffle: len {}, {:?}", self.content.len(), self); |
|
118 debug!("Deck shuffled"); |
104 // shufflers: |
119 // shufflers: |
105 // * naive: swap cards n times |
120 // * naive: swap cards n times |
106 // * kgb: half the deck, take 1..4 cards sequentially from each |
121 // * kgb: half the deck, take 1..4 cards sequentially from each |
107 // * grin: take 1..6 from front and put at bottom |
122 // * grin: take 1..6 from front and put at bottom |
108 |
123 |
112 let c2 = rng.gen_range(0 .. self.content.len()); |
127 let c2 = rng.gen_range(0 .. self.content.len()); |
113 if c1 != c2 { |
128 if c1 != c2 { |
114 self.content.swap(c1, c2); |
129 self.content.swap(c1, c2); |
115 } |
130 } |
116 } |
131 } |
|
132 trace!("Deck after shuffle: len {}, {:?}", self.content.len(), self); |
117 } |
133 } |
118 |
134 |
119 // get top card from deck |
135 // get top card from deck |
120 fn pop( &mut self ) -> Option<Card> { |
136 fn pop( &mut self ) -> Option<Card> { |
121 self.content.pop_front() |
137 self.content.pop_front() |
122 } |
138 } |
123 |
139 |
124 // put a card into the bottom of the deck |
140 // put a card into the bottom of the deck |
125 fn push( &mut self, c: Card ) { |
141 fn push( &mut self, c: Card ) { |
126 self.content.push_back(c); |
142 self.content.push_back(c); |
|
143 } |
|
144 |
|
145 fn push_cards( &mut self, cards: VecDeque<Card> ) { |
|
146 trace!("Collecting back, deck len is {}, cards {}", self.content.len(), cards.len()); |
|
147 cards.into_iter().for_each( |card| self.push(card) ); |
|
148 trace!("Deck len is {}", self.content.len()); |
127 } |
149 } |
128 |
150 |
129 fn len( &self ) -> usize { |
151 fn len( &self ) -> usize { |
130 self.content.len() |
152 self.content.len() |
131 } |
153 } |
137 panic!("get_nth: index {} out of bounds ({})!", n, self.content.len()); |
159 panic!("get_nth: index {} out of bounds ({})!", n, self.content.len()); |
138 } |
160 } |
139 } |
161 } |
140 } |
162 } |
141 |
163 |
|
164 /*** Player ****/ |
142 #[derive(Debug)] |
165 #[derive(Debug)] |
143 struct Player { |
166 struct Player { |
144 name: String, |
167 name: String, |
145 hand: Deck, |
168 hand: Deck, |
146 pile: Vec<Card>, |
169 pile: VecDeque<Card>, |
147 game_point: i32, |
170 game_point: i32, |
148 total_point: i32, |
171 total_point: i32, |
149 rows_busted: i32, |
172 rows_busted: i32, |
|
173 wins: i32, |
150 } |
174 } |
151 |
175 |
152 impl Player { |
176 impl Player { |
153 fn new(name: String)->Self { |
177 fn new(name: String)->Self { |
|
178 debug!("Player {} created", name); |
154 Player { |
179 Player { |
155 name, |
180 name, |
156 hand: Deck::new_empty(), |
181 hand: Deck::new_empty(), |
157 pile: Vec::new(), |
182 pile: VecDeque::new(), |
158 game_point: 0, |
183 game_point: 0, |
159 total_point: 0, |
184 total_point: 0, |
160 rows_busted: 0, |
185 rows_busted: 0, |
|
186 wins: 0, |
161 } |
187 } |
162 } |
188 } |
163 |
189 |
164 // get one card from th dealer |
190 // get one card from th dealer |
165 fn get_card( &mut self, card: Card ) { |
191 fn get_card( &mut self, card: Card ) { |
|
192 trace!("Player {} got a card {:?}, cards before {}", self.name, &card, self.hand.len()); |
166 self.hand.push(card); |
193 self.hand.push(card); |
167 } |
194 } |
168 |
195 |
169 // throw a card from hand to the table |
196 // throw a card from hand to the table |
170 fn throw_card( &mut self )->Card { |
197 fn throw_card( &mut self )->Card { |
171 if let Some(c) = self.hand.pop() { |
198 if let Some(c) = self.hand.pop() { |
|
199 trace!("Player {} throws a card {:?}", self.name, &c); |
172 c |
200 c |
173 } else { |
201 } else { |
174 panic!("throw_card: Player {} has no card in hand!", self.name); |
202 panic!("throw_card: Player {} has no card in hand!", self.name); |
175 } |
203 } |
176 } |
204 } |
177 |
205 |
178 // get a busted row of cards |
206 // get a busted row of cards |
179 fn get_pile( &mut self, cards: VecDeque<Card> ) { |
207 fn give_pile( &mut self, cards: VecDeque<Card> ) { |
180 for c in cards.into_iter() { |
208 for c in cards.into_iter() { |
181 self.game_point += c.points as i32; |
209 self.game_point += c.points as i32; |
182 self.pile.push(c); |
210 self.pile.push_back(c); |
183 } |
211 } |
184 self.rows_busted += 1; |
212 self.rows_busted += 1; |
|
213 trace!("Player {} got busted, count {}", self.name, &self.rows_busted); |
185 } |
214 } |
186 |
215 |
187 // ask the player their score |
216 // ask the player their score |
188 fn tell_points( self ) -> i32 { |
217 fn tell_points( self ) -> i32 { |
189 self.game_point |
218 self.game_point |
190 } |
219 } |
191 |
220 |
|
221 fn inc_wins( &mut self ) { |
|
222 self.wins += 1; |
|
223 } |
|
224 |
192 // give back cards from the pile |
225 // give back cards from the pile |
193 fn give_pile( &mut self ) -> Vec<Card> { |
226 fn get_pile( &mut self ) -> VecDeque<Card> { |
|
227 trace!("Player {} gives back their pile", self.name); |
194 mem::take( &mut self.pile ) |
228 mem::take( &mut self.pile ) |
195 // same effect: |
229 // same effect: |
196 // self.pile.drain(..).collect() |
230 // self.pile.drain(..).collect() |
197 |
231 |
198 // very cumbersome manual fiddling (also reverted...) |
232 // very cumbersome manual fiddling (also reverted...) |
220 |
254 |
221 if self.pile.len() > 0 { |
255 if self.pile.len() > 0 { |
222 panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len()); |
256 panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len()); |
223 } |
257 } |
224 |
258 |
|
259 trace!("Player {} closing round; points={} total so far {}", self.name, self.game_point, self.total_point); |
225 self.total_point += self.game_point; |
260 self.total_point += self.game_point; |
226 self.game_point = 0; |
261 self.game_point = 0; |
227 } |
262 } |
228 } |
263 |
229 |
264 // card too small: pick a row to collect from the rows |
|
265 fn pick_row_for_small_card( &self, rows: &Vec<Row>, playercard: &Card ) -> usize { |
|
266 trace!("Player {} picking a row for small card, card {:?}, rows {:?}", self.name, playercard, rows); |
|
267 |
|
268 // contains the summary point for each row |
|
269 let mut row_points = Vec::new(); |
|
270 // the smallest row score |
|
271 let mut smallest = 999; |
|
272 // how many rows have the same smallest score |
|
273 let mut same_point = 0; |
|
274 // the first smallest row_id |
|
275 let mut smallest_rowid = 255; |
|
276 |
|
277 for rowid in 0 .. rows.len() { |
|
278 // DEBUG |
|
279 // println!("pick_row_for_small_card: rowlen {}, rowid {}", rows.len(), rowid); |
|
280 row_points.push( rows[rowid].sum() ); |
|
281 |
|
282 if row_points[rowid] < smallest { |
|
283 // we have a new smallest row |
|
284 smallest = row_points[rowid]; |
|
285 same_point = 0; |
|
286 smallest_rowid = rowid; |
|
287 |
|
288 } else if row_points[rowid] == smallest { |
|
289 // we have another row with same point as smallest |
|
290 same_point += 1; |
|
291 } |
|
292 } |
|
293 |
|
294 if same_point < 1 { |
|
295 // we have one smallest row |
|
296 smallest_rowid.try_into().unwrap() // it's tiny, will fit into u8 |
|
297 |
|
298 } else { |
|
299 // bored, we pick the first now anyway |
|
300 smallest_rowid.try_into().unwrap() |
|
301 } |
|
302 |
|
303 } |
|
304 } |
|
305 |
|
306 /*** Row ****/ |
230 // a row of cards on the table (max 5) |
307 // a row of cards on the table (max 5) |
231 #[derive(Debug)] |
308 #[derive(Debug)] |
232 struct Row { |
309 struct Row { |
233 cards: VecDeque<Card>, |
310 cards: VecDeque<Card>, |
234 } |
311 } |
241 cards: VecDeque::new(), |
318 cards: VecDeque::new(), |
242 } |
319 } |
243 } |
320 } |
244 |
321 |
245 fn push_or_collect( &mut self, card: Card ) -> Option<VecDeque<Card>> { |
322 fn push_or_collect( &mut self, card: Card ) -> Option<VecDeque<Card>> { |
|
323 trace!("Called push_or_collect on row {:?}", &self); |
246 if self.cards.len() < Self::MAX_LEN { |
324 if self.cards.len() < Self::MAX_LEN { |
|
325 trace!("Less than {} cards, putting at the end", Self::MAX_LEN); |
247 self.cards.push_back(card); |
326 self.cards.push_back(card); |
248 None |
327 None |
249 |
328 |
250 } else { |
329 } else { |
|
330 trace!("Row is full, len {}, maxlen {}", self.cards.len(), Self::MAX_LEN); |
251 // row overflow |
331 // row overflow |
252 let row_cards = mem::take( &mut self.cards ); |
332 let row_cards = mem::take( &mut self.cards ); |
253 self.cards.push_back(card); |
333 self.cards.push_back(card); |
254 if self.cards.len() != 1 { |
334 if self.cards.len() != 1 { |
255 panic!("New row must have one card, not {}", self.cards.len()); |
335 panic!("New row must have one card, not {}", self.cards.len()); |
256 } |
336 } |
257 Some(row_cards) |
337 Some(row_cards) |
258 } |
338 } |
259 } |
339 } |
260 |
340 |
|
341 fn take_row( &mut self ) -> VecDeque<Card> { |
|
342 // take cards and empty the row |
|
343 mem::take( &mut self.cards ) |
|
344 } |
|
345 |
261 fn last_card_value(&self) -> i8 { |
346 fn last_card_value(&self) -> i8 { |
262 println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len()); |
347 // println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len()); |
263 self.cards.get( self.cards.len()-1 ).unwrap().value |
348 self.cards.get( self.cards.len()-1 ).unwrap().value |
264 } |
349 } |
265 } |
350 |
266 |
351 // sum of row card points |
|
352 fn sum(&self) -> i32 { |
|
353 let mut sum: i32 = 0; |
|
354 self.cards.iter().for_each(|card| { |
|
355 sum += card.points as i32; |
|
356 }); |
|
357 sum |
|
358 } |
|
359 } |
|
360 |
|
361 /*** PlayerCard ****/ |
267 #[derive(Debug)] |
362 #[derive(Debug)] |
268 struct PlayerCard { |
363 struct PlayerCard { |
269 player_id: i32, |
364 player_id: i32, |
270 card: Card, |
365 card: Card, |
271 } |
366 } |
309 rows.push( row ); |
405 rows.push( row ); |
310 } |
406 } |
311 |
407 |
312 Table { |
408 Table { |
313 rows, |
409 rows, |
314 player_cards: Vec::new(), |
410 player_cards: VecDeque::new(), |
315 } |
411 } |
316 } |
412 } |
317 |
413 |
318 fn lay_player_card( &mut self, card: Card, player_id: i32 ) { |
414 fn lay_player_card( &mut self, card: Card, player_id: i32 ) { |
319 self.player_cards.push( PlayerCard { player_id, card } ); |
415 self.player_cards.push_back( PlayerCard { player_id, card } ); |
320 } |
416 } |
321 |
417 |
322 fn sort_cards( &mut self ) { |
418 fn sort_cards( &mut self ) { |
323 self.player_cards.sort_by( |a,b| b.card.cmp(&a.card) ); |
419 self.player_cards.make_contiguous().sort_by( |a,b| b.card.cmp(&a.card) ); |
|
420 } |
|
421 |
|
422 fn has_player_cards( &self ) -> bool { |
|
423 self.player_cards.len() > 0 |
324 } |
424 } |
325 |
425 |
326 fn get_smallest_player_card( &mut self ) -> PlayerCard { |
426 fn get_smallest_player_card( &mut self ) -> PlayerCard { |
327 self.player_cards.pop().expect("out of player cards on table") |
427 // FIXME: check! |
328 } |
428 self.player_cards.pop_back().expect("out of player cards on table") |
329 |
429 } |
330 fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<i8> { |
430 |
|
431 fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<usize> { |
331 // get the row id with last card closest smaller to players' |
432 // get the row id with last card closest smaller to players' |
332 todo!() |
433 let row_heads = self.get_row_heads(); |
333 } |
434 let mut closest_val = None; |
334 |
435 let mut diff = 127; |
335 fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: i8 ) -> Option<VecDeque<Card>> { |
436 for i in 0..row_heads.len() { |
|
437 if row_heads[i] < pcard.card.value && pcard.card.value - row_heads[i] < diff { |
|
438 closest_val = Some(i); |
|
439 diff = pcard.card.value - row_heads[i]; |
|
440 // println!("DEBUG: pcard {}, row {}, head {}, diff {}, closest {:?}", pcard.card.value, i, row_heads[i], diff, closest_val); |
|
441 } |
|
442 } |
|
443 |
|
444 closest_val |
|
445 } |
|
446 |
|
447 fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: usize ) -> Option<VecDeque<Card>> { |
336 self.rows[row_id as usize].push_or_collect(pcard.card) |
448 self.rows[row_id as usize].push_or_collect(pcard.card) |
337 } |
449 } |
338 } |
450 |
339 |
451 fn get_row_heads( &self ) -> Vec<i8> { |
|
452 let mut heads: Vec<i8> = Vec::new(); |
|
453 for i in 0..self.rows.len() { |
|
454 heads.push( self.rows[i].last_card_value() ); |
|
455 } |
|
456 heads |
|
457 } |
|
458 |
|
459 // take a whole row and hand it over |
|
460 fn take_row( &mut self, row_id: usize ) -> VecDeque<Card> { |
|
461 self.rows[row_id].take_row() |
|
462 } |
|
463 |
|
464 // collect remaining cards in the rows at the end of round |
|
465 fn collect_rows( &mut self ) -> VecDeque<Card> { |
|
466 let mut cards = VecDeque::new(); |
|
467 for row in 0..self.rows.len() { |
|
468 self.rows[row] |
|
469 .take_row() |
|
470 .into_iter() |
|
471 .for_each(|card| cards.push_back(card)); |
|
472 } |
|
473 cards |
|
474 } |
|
475 } |
|
476 |
|
477 |
|
478 /*** Game ****/ |
|
479 |
|
480 struct GameStat { |
|
481 game_count: i64, |
|
482 shuffle_count: i64, |
|
483 start_time: Instant, // use start_time.elapsed().as_nanos() or .as_secs() |
|
484 } |
340 |
485 |
341 fn game() { |
486 fn game() { |
342 let mut cnt_shuffle = 0; |
487 let mut stats = GameStat { game_count:0, shuffle_count: 0, start_time: Instant::now() }; |
343 |
488 |
344 let mut deck = Deck::new(); |
489 let mut deck = Deck::new(); |
345 |
490 |
346 let player_names = vec![ "grin", "moni", "icbalint", "orsi", "topi", "kgb", "zsu", "csilla" ]; |
491 let player_names = vec![ "grin", "moni", "icbalint", "orsi", "topi", "kgb", "zsu", "csilla" ]; |
347 let mut players: Vec<Player> = player_names.iter().map( |n| Player::new(n.to_string()) ).collect(); |
492 let mut players: Vec<Player> = player_names.iter().map( |n| Player::new(n.to_string()) ).collect(); |
348 |
493 |
349 let player_count = players.len(); // pc - 1 |
494 let player_count = players.len(); // pc - 1 |
350 |
495 |
351 for _cnt_game in 1..=2 { |
496 for cnt_game in 1..=GAME_ROUNDS { |
|
497 debug!("Game round {} starts", cnt_game); |
352 deck.shuffle(); |
498 deck.shuffle(); |
353 cnt_shuffle += 1; |
499 stats.shuffle_count += 1; |
|
500 stats.game_count += 1; |
354 |
501 |
355 // dealing |
502 // dealing |
|
503 debug!("Dealing."); |
356 for i in 1..=10 { |
504 for i in 1..=10 { |
357 for player in 0 .. player_count { |
505 for player in 0 .. player_count { |
358 players[player].get_card( deck.pop().expect("Deck is empty while dealing to players") ); |
506 players[player].get_card( deck.pop().expect("Deck is empty while dealing to players") ); |
359 } |
507 } |
360 } |
508 } |
361 |
509 |
362 // we need 5 crds from deck |
510 // we need 5 crds from deck |
363 let mut cards = Vec::new(); |
511 debug!("Building the rows."); |
|
512 let mut cards = VecDeque::new(); |
364 for i in 1..=5 { |
513 for i in 1..=5 { |
365 cards.push( deck.pop().expect("deck empty before starting the game") ); |
514 cards.push_back( deck.pop().expect("deck empty before starting the game") ); |
366 } |
515 } |
367 println!("We push 5 cards to rows: {:?}\n", cards); |
516 // println!("We push 5 cards to rows: {:?}\n", cards); |
368 let mut table = Table::new(cards); |
517 let mut table = Table::new(cards); |
369 |
518 |
370 // DEBUG |
519 // DEBUG |
371 println!("Table: {:?}\n", table); |
520 /* println!("Table: {:?}\n", table); |
372 println!("PLayers: {:?}\n", players); |
521 println!("PLayers: {:?}\n", players); |
373 println!("Deck: {:?}\n", deck); |
522 println!("Deck: {:?}\n", deck); |
374 |
523 */ |
|
524 debug!("We have the table ready: {:?}", table); |
375 |
525 |
376 // playing |
526 // playing |
|
527 debug!("Players start taking turns"); |
377 for turn in 1..=10 { |
528 for turn in 1..=10 { |
|
529 debug!("Turn {}!", turn); |
|
530 trace!("The table: {:?}", table); |
378 |
531 |
379 // everyone puts a card face down |
532 // everyone puts a card face down |
380 for player in 0 .. player_count { |
533 for player in 0 .. player_count { |
381 let player_id: i32 = player.try_into().unwrap(); |
534 let player_id: i32 = player.try_into().unwrap(); |
382 // get a card from the player |
535 // get a card from the player |
384 // put it on the table ("turned face down") |
537 // put it on the table ("turned face down") |
385 table.lay_player_card( topcard, player_id ); |
538 table.lay_player_card( topcard, player_id ); |
386 } |
539 } |
387 |
540 |
388 // process cards |
541 // process cards |
|
542 debug!("The Table process the throws."); |
389 table.sort_cards(); |
543 table.sort_cards(); |
390 |
544 |
391 let smallest = table.get_smallest_player_card(); |
545 while table.has_player_cards() { |
392 |
546 let smallest = table.get_smallest_player_card(); |
393 let closest_row = table.get_closest_row(&smallest); |
547 trace!("Take smallest card {:?}", &smallest); |
394 match closest_row { |
548 |
395 Some(rowid) => { |
549 let closest_row = table.get_closest_row(&smallest); |
396 let player_id: usize = smallest.player_id.try_into().unwrap(); |
550 trace!("Choose closest row: {:?}", closest_row); |
397 let overflow = table.put_card_into_row(smallest, rowid); |
551 |
398 if let Some(cards) = overflow { |
552 match closest_row { |
399 // row is full, got pile |
553 Some(rowid) => { |
400 // player gets pile, card gets into row head |
554 debug!("Putting down card into row {}", rowid); |
401 players[ player_id ].get_pile( cards ); |
555 let player_id: usize = smallest.player_id.try_into().unwrap(); |
|
556 let overflow = table.put_card_into_row(smallest, rowid); |
|
557 if let Some(cards) = overflow { |
|
558 // row is full, got pile |
|
559 debug!("Row is busted, {} collects", players[player_id].name); |
|
560 // player gets pile, card gets into row head |
|
561 players[ player_id ].give_pile( cards ); |
|
562 } |
|
563 }, |
|
564 None => { |
|
565 // card too small, need to pick row! |
|
566 let player_id: usize = smallest.player_id.try_into().unwrap(); |
|
567 debug!("Too small from {}, picking row", players[player_id].name); |
|
568 // pick any row to take |
|
569 let rowid = players[ player_id ].pick_row_for_small_card(&table.rows, &smallest.card); |
|
570 trace!("Picked row {}", rowid); |
|
571 // take the row cards |
|
572 let cards = table.take_row(rowid); |
|
573 trace!("Took cards: {:?}", cards); |
|
574 players[ player_id ].give_pile( cards ); |
|
575 // put new card in the row |
|
576 let overflow = table.put_card_into_row(smallest, rowid); |
|
577 if let Some(c) = overflow { |
|
578 panic!("Player took whole row and it's already full"); |
|
579 } |
402 } |
580 } |
403 }, |
|
404 None => { |
|
405 // card too small, need to pick row! |
|
406 todo!(); |
|
407 } |
581 } |
408 } |
582 } |
409 |
|
410 } |
583 } |
411 |
584 |
412 // end of round |
585 // end of round |
413 |
586 info!("Round finished, len is {} µsec", stats.start_time.elapsed().as_micros()); |
414 // recollect deck |
587 |
415 |
588 debug!("End of round, counting and collecting back piles"); |
416 panic!("FInish now."); |
589 let mut winners: Vec<usize> = Vec::new(); |
|
590 let mut winscore: i32 = i32::MAX-1; |
|
591 |
|
592 for i in 0..player_count { |
|
593 info!("Player {} has {} points", players[i].name, players[i].game_point); |
|
594 |
|
595 if players[i].game_point < winscore { |
|
596 trace!("New winner {} with score {}", players[i].name, players[i].game_point); |
|
597 winners.clear(); |
|
598 winners.push(i); |
|
599 winscore = players[i].game_point; |
|
600 |
|
601 } else if players[i].game_point == winscore { |
|
602 trace!("New co-winner {} with score {}", players[i].name, players[i].game_point); |
|
603 winners.push(i); |
|
604 } |
|
605 trace!("The list of winners is {:?}", winners); |
|
606 |
|
607 // get pile from player |
|
608 let cards = players[i].get_pile(); |
|
609 // and give it back to the deck |
|
610 deck.push_cards(cards); |
|
611 // close player round and update stats |
|
612 players[i].close_round(); |
|
613 } |
|
614 |
|
615 // collect cards from table |
|
616 deck.push_cards( table.collect_rows() ); |
|
617 trace!("Shall have full deck now, len {}", deck.content.len()); |
|
618 |
|
619 let mut finals = Vec::new(); |
|
620 for i in winners.iter() { |
|
621 players[*i].inc_wins(); |
|
622 } |
|
623 |
|
624 for i in winners { |
|
625 finals.push( &players[i].name ); |
|
626 } |
|
627 info!("The winner(s): {:?}", &finals); |
|
628 |
|
629 /* players.iter().for_each(|player| { |
|
630 println!("Player {} has {} points", player.name, player.game_point); |
|
631 let cards = player.get_pile(); |
|
632 deck.push_cards(cards); |
|
633 player.close_round(); |
|
634 }); |
|
635 */ |
|
636 } |
|
637 |
|
638 println!("Totals (game time {} µs, or {} s), {} games played ({} shuffles):", |
|
639 stats.start_time.elapsed().as_micros(), |
|
640 stats.start_time.elapsed().as_secs(), |
|
641 stats.game_count, |
|
642 stats.shuffle_count, |
|
643 ); |
|
644 |
|
645 players.sort_by( |a, b| a.total_point.partial_cmp(&b.total_point).unwrap() ); |
|
646 |
|
647 for i in 0..players.len() { |
|
648 let p = &players[i]; |
|
649 println!("Player {} has wins {}, score {} (busted {} times)", p.name, p.wins, p.total_point, p.rows_busted); |
417 } |
650 } |
418 } |
651 } |
419 |
652 |
420 #[cfg(test)] |
653 #[cfg(test)] |
421 mod tests { |
654 mod tests { |
422 use core::panic; |
655 use core::panic; |
423 use std::collections::VecDeque; |
656 use std::collections::VecDeque; |
424 |
657 |
425 use rand::Rng; |
658 use rand::Rng; |
426 |
659 |
427 use crate::{Card, Player, Row}; |
660 use crate::{Card, Player, Row, Table, PlayerCard}; |
428 |
661 |
429 #[test] |
662 #[test] |
430 fn card_values() { |
663 fn card_values() { |
431 let card_values = vec![1,2,5,10,33,55,77]; |
664 let card_values = vec![1,2,5,10,33,55,77]; |
432 let card_points = vec![1,1,2,3, 5, 7, 5]; |
665 let card_points = vec![1,1,2,3, 5, 7, 5]; |
441 fn player_take_pile() { |
674 fn player_take_pile() { |
442 // create a player |
675 // create a player |
443 let mut p = Player::new("bob".to_string()); |
676 let mut p = Player::new("bob".to_string()); |
444 // create a pile |
677 // create a pile |
445 let mut pile = VecDeque::new(); |
678 let mut pile = VecDeque::new(); |
446 let mut refpile = Vec::new(); |
679 let mut refpile = VecDeque::new(); |
447 for i in 5..10 { |
680 for i in 5..10 { |
448 let c = Card::new(i); |
681 let c = Card::new(i); |
449 pile.push_back(c); |
682 pile.push_back(c); |
450 let c = Card::new(i); |
683 let c = Card::new(i); |
451 refpile.push(c); |
684 refpile.push_back(c); |
452 } |
685 } |
453 // add the pile to player |
686 // give the pile to player |
454 p.get_pile(pile); |
687 p.give_pile(pile); |
455 assert!( p.rows_busted == 1 ); |
688 assert!( p.rows_busted == 1 ); |
456 |
689 |
457 // get back the pile from player |
690 // get back the pile from player |
458 // p = p.gimme_pile(); |
691 // p = p.gimme_pile(); |
459 let pile = p.give_pile(); |
692 let pile = p.get_pile(); |
460 |
693 |
461 // the pile we got shall be same as the pile we gave |
694 // the pile we got shall be same as the pile we gave |
462 // this check is O(n^2), doesn't matter for less than 100 items |
695 // this check is O(n^2), doesn't matter for less than 100 items |
|
696 assert_eq!( pile, refpile ); |
463 assert!( pile.iter().all( |item| refpile.contains(item)) ); |
697 assert!( pile.iter().all( |item| refpile.contains(item)) ); |
464 |
698 |
465 let mut pile = VecDeque::new(); |
699 let mut pile = VecDeque::new(); |
466 for i in 4..=9 { |
700 for i in 4..=9 { |
467 let c = Card::new(i); |
701 let c = Card::new(i); |
468 pile.push_back(c); |
702 pile.push_back(c); |
469 } |
703 } |
470 p.get_pile(pile); |
704 p.give_pile(pile); |
471 assert!( p.rows_busted == 2 ); |
705 assert!( p.rows_busted == 2 ); |
472 } |
706 } |
473 |
707 |
474 #[test] |
708 #[test] |
475 fn row_push() { |
709 fn row_push() { |
476 let mut row = Row::new(); |
710 let mut row = Row::new(); |
477 let mut refcard = Vec::new(); // reference vec to check |
711 let mut refcard = VecDeque::new(); // reference vec to check |
478 for i in 1..=7 { |
712 for i in 1..=7 { |
479 let cval = i+5; |
713 let cval = i+5; |
480 let card = Card::new(cval); |
714 let card = Card::new(cval); |
481 // push a card into the row |
715 // push a card into the row |
482 if let Some(cards) = row.push_or_collect(card) { |
716 if let Some(cards) = row.push_or_collect(card) { |
488 } else { |
722 } else { |
489 println!("push success {}", i); |
723 println!("push success {}", i); |
490 } |
724 } |
491 // remember the correct vec for checking |
725 // remember the correct vec for checking |
492 let card = Card::new(cval); |
726 let card = Card::new(cval); |
493 refcard.push(card); |
727 refcard.push_back(card); |
494 |
728 |
495 // check card value |
729 // check card value |
496 assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval ); |
730 assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval ); |
497 } |
731 } |
498 assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() ); |
732 assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() ); |
499 } |
733 } |
500 |
734 |
501 #[test] |
735 #[test] |
502 fn sort_cards() { |
736 fn sort_cards() { |
503 let mut cards: Vec<Card> = Vec::new(); |
737 let mut cards: VecDeque<Card> = VecDeque::new(); |
504 let mut rng = rand::thread_rng(); |
738 let mut rng = rand::thread_rng(); |
505 for i in 1..50 { |
739 for i in 1..50 { |
506 let n = rng.gen_range(1..104); |
740 let n = rng.gen_range(1..104); |
507 cards.push( Card::new(n) ); |
741 cards.push_back( Card::new(n) ); |
508 } |
742 } |
509 cards.sort(); |
743 cards.make_contiguous().sort(); |
510 |
744 |
511 for i in 1..cards.len() { |
745 for i in 1..cards.len() { |
512 assert!( cards[i-1].value <= cards[i].value, "Bad ordering: {} > {}", cards[i-1].value,cards[i].value ); |
746 assert!( cards[i-1].value <= cards[i].value, "Bad ordering: {} > {}", cards[i-1].value,cards[i].value ); |
513 } |
747 } |
514 } |
748 } |
515 |
749 |
|
750 #[test] |
|
751 fn check_closest_row() { |
|
752 let table = generate_table(); |
|
753 let pcard = PlayerCard{ player_id: 42, card: Card::new(42) }; |
|
754 let closest = table.get_closest_row(&pcard); |
|
755 assert_eq!( closest, Some(3) ); // index from 0 |
|
756 } |
|
757 |
|
758 #[test] |
|
759 fn check_smallest_player_card() { |
|
760 let mut table = generate_table(); |
|
761 |
|
762 let mut player_id = 1; |
|
763 vec![103, 8, 71, 93, 6].into_iter().for_each(|c| { |
|
764 table.lay_player_card( Card::new(c), player_id); |
|
765 player_id += 1; |
|
766 }); |
|
767 |
|
768 let smallest = table.get_smallest_player_card(); |
|
769 assert_eq!( smallest, PlayerCard{ player_id: 5, card: Card::new(6) } ); |
|
770 } |
|
771 |
|
772 fn generate_table() -> Table { |
|
773 let mut row_cards = VecDeque::new(); |
|
774 vec![5,7,10,33,70].into_iter().for_each(|c| row_cards.push_back( Card::new(c) )); |
|
775 let table = Table::new(row_cards); |
|
776 table |
|
777 } |
516 } |
778 } |
517 |
779 |
518 /* |
780 /* |
519 |
781 |
520 - 1-104 lap, |
782 - 1-104 lap, |