1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::card::Card;
use crate::hand::Hand;
use crate::action::Action;
#[derive(Debug, Clone)]
pub struct Player {
pub id: usize,
pub name: String,
pub chips: u32,
pub seat_position: usize, // Physical seat at the table
pub hand: Hand,
pub bet_amount: u32,
pub is_folded: bool,
pub is_all_in: bool,
pub is_dealer: bool,
}
impl Player {
pub fn new(id: usize, name: String, chips: u32, seat: usize) -> Self {
Self {
id,
name,
chips,
seat_position: seat,
hand: Hand::new(),
bet_amount: 0,
is_folded: false,
is_all_in: false,
is_dealer: false,
}
}
pub fn receive_card(&mut self, card: Card) {
self.hand.add_card(card);
}
/// Bet a certain amount of chips
pub fn bet(&mut self, amount: u32) -> u32 {
// Limit the bet to player's available chips
let actual_amount = amount.min(self.chips);
// Update chip counts
self.chips -= actual_amount;
self.bet_amount += actual_amount;
// Check if player is now all-in
if self.chips == 0 {
self.is_all_in = true;
}
actual_amount
}
pub fn fold(&mut self) {
self.is_folded = true;
}
pub fn collect_winnings(&mut self, amount: u32) {
self.chips += amount;
}
pub fn reset_for_new_hand(&mut self) {
self.hand.clear();
self.bet_amount = 0;
self.is_folded = false;
self.is_all_in = false;
}
/// Check if the player can perform the given action
pub fn can_perform_action(&self, action: &Action, current_bet: u32) -> bool {
// If player has folded or is all-in, they can't take any action
if self.is_folded || self.is_all_in {
return false;
}
match action {
Action::Fold => true, // Player can always fold
Action::Bet(amount) => {
if *amount == 0 {
// Check is only valid if no bet to call
return self.bet_amount == current_bet;
}
// If player is betting all their chips, it's a valid all-in
if *amount == self.chips {
return true;
}
// Otherwise, ensure player has enough chips
if *amount > self.chips {
return false;
}
// If betting less than the amount needed to call, it's not valid
// (unless it's an all-in, which we already checked)
if self.bet_amount + *amount < current_bet {
return false;
}
true
},
Action::Post(amount) => *amount <= self.chips, // Can only post if have enough chips
}
}
}