pub struct DealerHand { /* private fields */ }Expand description
The dealer’s hand.
Implementations§
Source§impl DealerHand
impl DealerHand
Sourcepub fn cards(&self) -> &[Card]
pub fn cards(&self) -> &[Card]
Returns all cards in the hand.
Examples found in repository?
examples/cli_blackjack.rs (line 337)
336fn format_dealer(dealer: &bjrs::DealerHand) -> String {
337 if dealer.cards().is_empty() {
338 return "(no cards)".to_string();
339 }
340
341 if dealer.is_hole_revealed() {
342 dealer
343 .cards()
344 .iter()
345 .map(format_card)
346 .collect::<Vec<_>>()
347 .join(" ")
348 } else {
349 let mut parts = Vec::new();
350 if let Some(card) = dealer.up_card() {
351 parts.push(format_card(card));
352 }
353 if dealer.len() > 1 {
354 parts.push("??".to_string());
355 }
356 parts.join(" ")
357 }
358}Sourcepub fn up_card(&self) -> Option<&Card>
pub fn up_card(&self) -> Option<&Card>
Returns the visible card (first card).
Examples found in repository?
examples/cli_blackjack.rs (line 350)
336fn format_dealer(dealer: &bjrs::DealerHand) -> String {
337 if dealer.cards().is_empty() {
338 return "(no cards)".to_string();
339 }
340
341 if dealer.is_hole_revealed() {
342 dealer
343 .cards()
344 .iter()
345 .map(format_card)
346 .collect::<Vec<_>>()
347 .join(" ")
348 } else {
349 let mut parts = Vec::new();
350 if let Some(card) = dealer.up_card() {
351 parts.push(format_card(card));
352 }
353 if dealer.len() > 1 {
354 parts.push("??".to_string());
355 }
356 parts.join(" ")
357 }
358}Sourcepub const fn is_hole_revealed(&self) -> bool
pub const fn is_hole_revealed(&self) -> bool
Returns whether the hole card is revealed.
Examples found in repository?
examples/cli_blackjack.rs (line 175)
169fn print_table(game: &Game, player_id: u8) {
170 let remaining = game.cards_remaining();
171 println!("\nShoe: {remaining} cards remaining");
172
173 let dealer = game.get_dealer_hand();
174 let dealer_view = format_dealer(&dealer);
175 let dealer_value = if dealer.is_hole_revealed() {
176 dealer.value()
177 } else {
178 dealer.visible_value()
179 };
180 println!("\nDealer: {dealer_view} (value {dealer_value})");
181
182 let hands = game.get_hands(player_id).unwrap_or_default();
183 let turn = game.current_turn();
184 for (index, hand) in hands.iter().enumerate() {
185 let marker = if index == turn.hand_index { "*" } else { " " };
186 println!(
187 "{} Hand {}: {} | value {} | bet {} | {:?}",
188 marker,
189 index,
190 format_hand(hand),
191 hand.value(),
192 hand.bet(),
193 hand.status()
194 );
195 }
196 println!();
197}
198
199fn print_table_final(game: &Game, player_id: u8) {
200 let remaining = game.cards_remaining();
201 println!("\nShoe: {remaining} cards remaining");
202
203 let dealer = game.get_dealer_hand();
204 println!(
205 "\nDealer: {} (value {})",
206 format_dealer(&dealer),
207 dealer.value()
208 );
209
210 let hands = game.get_hands(player_id).unwrap_or_default();
211 for (index, hand) in hands.iter().enumerate() {
212 println!(
213 "Hand {}: {} | value {} | bet {} | {:?}",
214 index,
215 format_hand(hand),
216 hand.value(),
217 hand.bet(),
218 hand.status()
219 );
220 }
221 println!();
222}
223
224fn format_actions(game: &Game, player_id: u8) -> String {
225 let availability = available_actions(game, player_id);
226 let mut parts = Vec::new();
227 parts.push(format_action("hit", "h", availability.hit));
228 parts.push(format_action("stand", "s", availability.stand));
229 parts.push(format_action("double", "d", availability.double));
230 parts.push(format_action("split", "p", availability.split));
231 parts.push(format_action("surrender", "u", availability.surrender));
232 format!("Actions: {}", parts.join(" "))
233}
234
235fn format_action(label: &str, key: &str, allowed: bool) -> String {
236 let text = format!("[{key}]{label}");
237 if allowed {
238 colorize(&text, "32")
239 } else {
240 colorize(&text, "90")
241 }
242}
243
244fn colorize(text: &str, code: &str) -> String {
245 format!("\u{1b}[{code}m{text}\u{1b}[0m")
246}
247
248struct ActionAvailability {
249 hit: bool,
250 stand: bool,
251 double: bool,
252 split: bool,
253 surrender: bool,
254}
255
256fn available_actions(game: &Game, player_id: u8) -> ActionAvailability {
257 if *game.state.lock() != GameState::PlayerTurn {
258 return ActionAvailability {
259 hit: false,
260 stand: false,
261 double: false,
262 split: false,
263 surrender: false,
264 };
265 }
266
267 if game.current_player() != Some(player_id) {
268 return ActionAvailability {
269 hit: false,
270 stand: false,
271 double: false,
272 split: false,
273 surrender: false,
274 };
275 }
276
277 let hands = game.get_hands(player_id).unwrap_or_default();
278 let turn = game.current_turn();
279 let Some(hand) = hands.get(turn.hand_index) else {
280 return ActionAvailability {
281 hit: false,
282 stand: false,
283 double: false,
284 split: false,
285 surrender: false,
286 };
287 };
288
289 if hand.status() != HandStatus::Active {
290 return ActionAvailability {
291 hit: false,
292 stand: false,
293 double: false,
294 split: false,
295 surrender: false,
296 };
297 }
298
299 let money = game.get_money(player_id).unwrap_or(0);
300 let bet = hand.bet();
301 let has_funds_for_double = money >= bet;
302 let has_funds_for_split = money >= bet;
303
304 let can_double_value = match game.options.double {
305 DoubleOption::Any => true,
306 DoubleOption::NineOrTen => hand.value() == 9 || hand.value() == 10,
307 DoubleOption::NineThrough11 => (9..=11).contains(&hand.value()),
308 DoubleOption::NineThrough15 => (9..=15).contains(&hand.value()),
309 DoubleOption::None => false,
310 _ => panic!("unhandled double option"),
311 };
312
313 let can_double = hand.len() == 2
314 && (!hand.is_from_split() || game.options.double_after_split)
315 && can_double_value
316 && has_funds_for_double;
317
318 let is_ace = hand.cards().first().is_some_and(|c| c.rank == 1);
319 let max_splits_reached = hands.len() > game.options.split as usize;
320 let can_split = hand.can_split()
321 && !max_splits_reached
322 && has_funds_for_split
323 && !(is_ace && hand.is_from_split() && game.options.split_aces_only_once);
324
325 let can_surrender = game.options.surrender && hand.len() == 2 && !hand.is_from_split();
326
327 ActionAvailability {
328 hit: true,
329 stand: true,
330 double: can_double,
331 split: can_split,
332 surrender: can_surrender,
333 }
334}
335
336fn format_dealer(dealer: &bjrs::DealerHand) -> String {
337 if dealer.cards().is_empty() {
338 return "(no cards)".to_string();
339 }
340
341 if dealer.is_hole_revealed() {
342 dealer
343 .cards()
344 .iter()
345 .map(format_card)
346 .collect::<Vec<_>>()
347 .join(" ")
348 } else {
349 let mut parts = Vec::new();
350 if let Some(card) = dealer.up_card() {
351 parts.push(format_card(card));
352 }
353 if dealer.len() > 1 {
354 parts.push("??".to_string());
355 }
356 parts.join(" ")
357 }
358}Sourcepub const fn reveal_hole(&mut self)
pub const fn reveal_hole(&mut self)
Reveals the hole card.
Sourcepub fn visible_value(&self) -> u8
pub fn visible_value(&self) -> u8
Calculates the visible value (only up card if hole not revealed).
Examples found in repository?
examples/cli_blackjack.rs (line 178)
169fn print_table(game: &Game, player_id: u8) {
170 let remaining = game.cards_remaining();
171 println!("\nShoe: {remaining} cards remaining");
172
173 let dealer = game.get_dealer_hand();
174 let dealer_view = format_dealer(&dealer);
175 let dealer_value = if dealer.is_hole_revealed() {
176 dealer.value()
177 } else {
178 dealer.visible_value()
179 };
180 println!("\nDealer: {dealer_view} (value {dealer_value})");
181
182 let hands = game.get_hands(player_id).unwrap_or_default();
183 let turn = game.current_turn();
184 for (index, hand) in hands.iter().enumerate() {
185 let marker = if index == turn.hand_index { "*" } else { " " };
186 println!(
187 "{} Hand {}: {} | value {} | bet {} | {:?}",
188 marker,
189 index,
190 format_hand(hand),
191 hand.value(),
192 hand.bet(),
193 hand.status()
194 );
195 }
196 println!();
197}Sourcepub fn value(&self) -> u8
pub fn value(&self) -> u8
Calculates the full value of the hand.
Examples found in repository?
examples/cli_blackjack.rs (line 176)
169fn print_table(game: &Game, player_id: u8) {
170 let remaining = game.cards_remaining();
171 println!("\nShoe: {remaining} cards remaining");
172
173 let dealer = game.get_dealer_hand();
174 let dealer_view = format_dealer(&dealer);
175 let dealer_value = if dealer.is_hole_revealed() {
176 dealer.value()
177 } else {
178 dealer.visible_value()
179 };
180 println!("\nDealer: {dealer_view} (value {dealer_value})");
181
182 let hands = game.get_hands(player_id).unwrap_or_default();
183 let turn = game.current_turn();
184 for (index, hand) in hands.iter().enumerate() {
185 let marker = if index == turn.hand_index { "*" } else { " " };
186 println!(
187 "{} Hand {}: {} | value {} | bet {} | {:?}",
188 marker,
189 index,
190 format_hand(hand),
191 hand.value(),
192 hand.bet(),
193 hand.status()
194 );
195 }
196 println!();
197}
198
199fn print_table_final(game: &Game, player_id: u8) {
200 let remaining = game.cards_remaining();
201 println!("\nShoe: {remaining} cards remaining");
202
203 let dealer = game.get_dealer_hand();
204 println!(
205 "\nDealer: {} (value {})",
206 format_dealer(&dealer),
207 dealer.value()
208 );
209
210 let hands = game.get_hands(player_id).unwrap_or_default();
211 for (index, hand) in hands.iter().enumerate() {
212 println!(
213 "Hand {}: {} | value {} | bet {} | {:?}",
214 index,
215 format_hand(hand),
216 hand.value(),
217 hand.bet(),
218 hand.status()
219 );
220 }
221 println!();
222}Sourcepub fn is_blackjack(&self) -> bool
pub fn is_blackjack(&self) -> bool
Returns whether the hand is a blackjack.
Sourcepub fn is_soft(&self) -> bool
pub fn is_soft(&self) -> bool
Returns whether the hand is soft (contains an ace counted as 11).
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of cards.
Examples found in repository?
examples/cli_blackjack.rs (line 353)
336fn format_dealer(dealer: &bjrs::DealerHand) -> String {
337 if dealer.cards().is_empty() {
338 return "(no cards)".to_string();
339 }
340
341 if dealer.is_hole_revealed() {
342 dealer
343 .cards()
344 .iter()
345 .map(format_card)
346 .collect::<Vec<_>>()
347 .join(" ")
348 } else {
349 let mut parts = Vec::new();
350 if let Some(card) = dealer.up_card() {
351 parts.push(format_card(card));
352 }
353 if dealer.len() > 1 {
354 parts.push("??".to_string());
355 }
356 parts.join(" ")
357 }
358}Trait Implementations§
Source§impl Clone for DealerHand
impl Clone for DealerHand
Source§fn clone(&self) -> DealerHand
fn clone(&self) -> DealerHand
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for DealerHand
impl Debug for DealerHand
Auto Trait Implementations§
impl Freeze for DealerHand
impl RefUnwindSafe for DealerHand
impl Send for DealerHand
impl Sync for DealerHand
impl Unpin for DealerHand
impl UnwindSafe for DealerHand
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more