1 /*** Table ****/ |
1 /// Implemantation of the playing Table. |
2 |
2 |
3 use std::collections::VecDeque; |
3 use std::collections::VecDeque; |
4 |
4 |
5 use crate::card::Card; |
5 use crate::card::Card; |
6 use crate::row::Row; |
6 use crate::row::Row; |
7 use crate::player::PlayerCard; |
7 use crate::player::PlayerCard; |
8 |
8 |
9 #[derive(Debug)] |
9 #[derive(Debug)] |
|
10 /// A playing Table, containing 5 [`Row`]s and some [`PlayerCard`]s. |
|
11 /// A Table can do some useful function with its cards, like picking |
|
12 /// closest row or moving cards. |
10 pub(crate) struct Table { |
13 pub(crate) struct Table { |
11 rows: Vec<Row>, |
14 rows: Vec<Row>, |
12 player_cards: VecDeque<PlayerCard>, // owned by a player |
15 player_cards: VecDeque<PlayerCard>, // owned by a player |
13 } |
16 } |
14 |
17 |
15 impl Table { |
18 impl Table { |
|
19 /// Creates a new `Table`, filling Rows from `row_cards`. |
16 pub(crate) fn new(row_cards: VecDeque<Card>) -> Self { |
20 pub(crate) fn new(row_cards: VecDeque<Card>) -> Self { |
|
21 // We have exactly 5 Rows. |
17 let mut rows = Vec::with_capacity(5); |
22 let mut rows = Vec::with_capacity(5); |
18 for card in row_cards { |
23 for card in row_cards { |
19 // create a new row then put a card into it |
24 // create a new row then put a card into it |
20 let mut row = Row::new(); |
25 let mut row = Row::new(); |
21 if let Some(_c) = row.push_or_collect(card) { |
26 if let Some(_) = row.push_or_collect(card) { |
|
27 // Row should have one card, so... mustn't happen. |
22 panic!("Freshly created row overflowed"); |
28 panic!("Freshly created row overflowed"); |
23 } |
29 } |
|
30 // Put the new row onto the Table. |
24 rows.push( row ); |
31 rows.push( row ); |
25 } |
32 } |
26 |
33 |
|
34 // And return the newly created Table. |
27 Table { |
35 Table { |
28 rows, |
36 rows, |
29 player_cards: VecDeque::new(), |
37 player_cards: VecDeque::new(), |
30 } |
38 } |
31 } |
39 } |
32 |
40 |
|
41 /// Gets a [`Card`] from a [`Player`] and put it into the `player_cards` area, |
|
42 /// remembering whose (`player_id`) card it was. |
33 pub(crate) fn lay_player_card( &mut self, card: Card, player_id: i32 ) { |
43 pub(crate) fn lay_player_card( &mut self, card: Card, player_id: i32 ) { |
34 self.player_cards.push_back( PlayerCard { player_id, card } ); |
44 self.player_cards.push_back( PlayerCard { player_id, card } ); |
35 } |
45 } |
36 |
46 |
|
47 /// Sort the [`Card`]s thrown by the [`Player`]s, since we'd need |
|
48 /// to get them ordered by value later. |
37 pub(crate) fn sort_cards( &mut self ) { |
49 pub(crate) fn sort_cards( &mut self ) { |
|
50 // Sorting a normal VecDeque is not possible since it may contain |
|
51 // holes, so we need to de-hole it first, then it's sortable (through |
|
52 // a returned pointer slice). |
38 self.player_cards.make_contiguous().sort_by( |a,b| b.card.cmp(&a.card) ); |
53 self.player_cards.make_contiguous().sort_by( |a,b| b.card.cmp(&a.card) ); |
39 } |
54 } |
40 |
55 |
|
56 /// Returns true if we have unprocessed Player cards on the table. |
41 pub(crate) fn has_player_cards( &self ) -> bool { |
57 pub(crate) fn has_player_cards( &self ) -> bool { |
42 self.player_cards.len() > 0 |
58 self.player_cards.len() > 0 |
43 } |
59 } |
44 |
60 |
|
61 /// Return the smallest player card on the table. |
|
62 /// FIXME: shall check whether it's ordered. |
45 pub(crate) fn get_smallest_player_card( &mut self ) -> PlayerCard { |
63 pub(crate) fn get_smallest_player_card( &mut self ) -> PlayerCard { |
46 // FIXME: check! |
64 // FIXME: check orderedness! |
|
65 // FIXME: check asking when empty! |
47 self.player_cards.pop_back().expect("out of player cards on table") |
66 self.player_cards.pop_back().expect("out of player cards on table") |
48 } |
67 } |
49 |
68 |
|
69 /// Return the row which is closest to the `pcard` arg, or None if |
|
70 /// all Row tails are larger. |
50 pub(crate) fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<usize> { |
71 pub(crate) fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<usize> { |
51 // get the row id with last card closest smaller to players' |
72 // get the row id with last card closest smaller to players' |
52 let row_heads = self.get_row_heads(); |
73 let row_tails = self.get_row_tails(); |
53 let mut closest_val = None; |
74 let mut closest_val = None; |
54 let mut diff = 127; |
75 let mut diff = 127; // larger than any |
55 for i in 0..row_heads.len() { |
76 // Check all the row tail cards |
56 if row_heads[i] < pcard.card.value && pcard.card.value - row_heads[i] < diff { |
77 for i in 0..row_tails.len() { |
57 closest_val = Some(i); |
78 if row_tails[i] < pcard.card.value && pcard.card.value - row_tails[i] < diff { |
58 diff = pcard.card.value - row_heads[i]; |
79 // it is smaller than pcard and closer than the old closest one: match! |
59 // println!("DEBUG: pcard {}, row {}, head {}, diff {}, closest {:?}", pcard.card.value, i, row_heads[i], diff, closest_val); |
80 // Store the row index |
|
81 closest_val = Some(i); |
|
82 diff = pcard.card.value - row_tails[i]; |
|
83 // debug!("DEBUG: pcard {}, row {}, head {}, diff {}, closest {:?}", pcard.card.value, i, row_heads[i], diff, closest_val); |
60 } |
84 } |
61 } |
85 } |
62 |
86 |
63 closest_val |
87 closest_val |
64 } |
88 } |
65 |
89 |
|
90 /// Put a [`Card`] into the `row_id` Row (tail). |
|
91 /// Returns `None` if ok or `Some(cards)` when the Row is full. |
66 pub(crate) fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: usize ) -> Option<VecDeque<Card>> { |
92 pub(crate) fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: usize ) -> Option<VecDeque<Card>> { |
67 self.rows[row_id as usize].push_or_collect(pcard.card) |
93 // We actually ask the Row to do it properly. |
|
94 self.rows[row_id].push_or_collect(pcard.card) |
68 } |
95 } |
69 |
96 |
70 pub(crate) fn get_row_heads( &self ) -> Vec<i8> { |
97 pub(crate) fn get_row_tails( &self ) -> Vec<i8> { |
71 let mut heads: Vec<i8> = Vec::new(); |
98 let mut heads: Vec<i8> = Vec::new(); |
72 for i in 0..self.rows.len() { |
99 for i in 0..self.rows.len() { |
73 heads.push( self.rows[i].last_card_value() ); |
100 heads.push( self.rows[i].last_card_value() ); |
74 } |
101 } |
75 heads |
102 heads |