diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-29 18:43:09 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-29 18:43:09 +0100 |
| commit | 08269639606c0481037cbde7ebaf2e0455460883 (patch) | |
| tree | 57c1f967e8836a1a7da84b1887d932e0067d538f /src | |
| parent | v2.2.0: add blackjack with reserved bets and hit/stand/double (diff) | |
| download | zagan-bet-08269639606c0481037cbde7ebaf2e0455460883.tar.gz zagan-bet-08269639606c0481037cbde7ebaf2e0455460883.zip | |
v2.2.1: forfeit blackjack bets when leaving or disconnecting
Diffstat (limited to '')
| -rw-r--r-- | src/client/core.rs | 18 | ||||
| -rw-r--r-- | src/client/games/blackjack.rs | 9 | ||||
| -rw-r--r-- | src/server/core.rs | 50 | ||||
| -rw-r--r-- | src/server/games/blackjack.rs | 4 |
4 files changed, 63 insertions, 18 deletions
diff --git a/src/client/core.rs b/src/client/core.rs index 6e9c28b..77761b4 100644 --- a/src/client/core.rs +++ b/src/client/core.rs | |||
| @@ -65,7 +65,7 @@ enum Pending { | |||
| 65 | RouletteSpin, | 65 | RouletteSpin, |
| 66 | BlackjackStart, | 66 | BlackjackStart, |
| 67 | BlackjackAction, | 67 | BlackjackAction, |
| 68 | BlackjackCancel, | 68 | BlackjackForfeit, |
| 69 | Ping, | 69 | Ping, |
| 70 | Echo, | 70 | Echo, |
| 71 | Info, | 71 | Info, |
| @@ -209,12 +209,16 @@ impl ClientCore { | |||
| 209 | } | 209 | } |
| 210 | } | 210 | } |
| 211 | } | 211 | } |
| 212 | Some(Pending::BlackjackCancel) => match parse_blackjack_response(reply) { | 212 | Some(Pending::BlackjackForfeit) => match parse_blackjack_response(reply) { |
| 213 | Ok(_) => { | 213 | Ok(state) => { |
| 214 | self.game.end_game(); | 214 | self.game.end_game(); |
| 215 | let message = format!( | ||
| 216 | "Game exited. Active hand forfeited ({} PLN lost).", | ||
| 217 | state.bet | ||
| 218 | ); | ||
| 215 | vec![ | 219 | vec![ |
| 216 | Effect::ClearRegion, | 220 | Effect::ClearRegion, |
| 217 | Effect::Print(vec!["Game exited.".to_string()]), | 221 | Effect::Print(vec![message]), |
| 218 | ] | 222 | ] |
| 219 | } | 223 | } |
| 220 | Err(message) => { | 224 | Err(message) => { |
| @@ -457,10 +461,10 @@ impl ClientCore { | |||
| 457 | Key::CtrlC => vec![Effect::Quit], | 461 | Key::CtrlC => vec![Effect::Quit], |
| 458 | Key::Char('q') => { | 462 | Key::Char('q') => { |
| 459 | if let Some(hand) = hand.filter(|hand| hand.phase == "player") { | 463 | if let Some(hand) = hand.filter(|hand| hand.phase == "player") { |
| 460 | self.game.set_blackjack_status("cancelling"); | 464 | self.game.set_blackjack_status("forfeiting"); |
| 461 | self.pending = Some(Pending::BlackjackCancel); | 465 | self.pending = Some(Pending::BlackjackForfeit); |
| 462 | vec![Effect::SendLine(format!( | 466 | vec![Effect::SendLine(format!( |
| 463 | "BLACKJACK_ACTION {} cancel", | 467 | "BLACKJACK_ACTION {} forfeit", |
| 464 | hand.session_id | 468 | hand.session_id |
| 465 | ))] | 469 | ))] |
| 466 | } else { | 470 | } else { |
diff --git a/src/client/games/blackjack.rs b/src/client/games/blackjack.rs index a34eb63..bad1781 100644 --- a/src/client/games/blackjack.rs +++ b/src/client/games/blackjack.rs | |||
| @@ -38,6 +38,7 @@ impl BlackjackGame { | |||
| 38 | "push" => "Push. Bet returned.".to_string(), | 38 | "push" => "Push. Bet returned.".to_string(), |
| 39 | "lose" => "Dealer wins.".to_string(), | 39 | "lose" => "Dealer wins.".to_string(), |
| 40 | "bust" => "Bust.".to_string(), | 40 | "bust" => "Bust.".to_string(), |
| 41 | "forfeit" => "Forfeited. Bet lost.".to_string(), | ||
| 41 | "cancelled" => "Cancelled.".to_string(), | 42 | "cancelled" => "Cancelled.".to_string(), |
| 42 | _ => "Hand complete.".to_string(), | 43 | _ => "Hand complete.".to_string(), |
| 43 | } | 44 | } |
| @@ -85,15 +86,15 @@ impl Game for BlackjackGame { | |||
| 85 | } | 86 | } |
| 86 | } | 87 | } |
| 87 | "dealing" => "Dealing...".to_string(), | 88 | "dealing" => "Dealing...".to_string(), |
| 88 | "cancelling" => "Cancelling...".to_string(), | 89 | "forfeiting" => "Forfeiting...".to_string(), |
| 89 | "done" => Self::result_text(&hand.result, hand.winnings), | 90 | "done" => Self::result_text(&hand.result, hand.winnings), |
| 90 | _ => "Press [SPACE] to deal.".to_string(), | 91 | _ => "Press [SPACE] to deal.".to_string(), |
| 91 | }; | 92 | }; |
| 92 | let controls = if status == "player" { | 93 | let controls = if status == "player" { |
| 93 | if hand.actions.iter().any(|action| action == "double") { | 94 | if hand.actions.iter().any(|action| action == "double") { |
| 94 | "[H]it [S]tand [D]ouble [Q]uit".to_string() | 95 | "[H]it [S]tand [D]ouble [Q] Forfeit".to_string() |
| 95 | } else { | 96 | } else { |
| 96 | "[H]it [S]tand [Q]uit".to_string() | 97 | "[H]it [S]tand [Q] Forfeit".to_string() |
| 97 | } | 98 | } |
| 98 | } else { | 99 | } else { |
| 99 | "[SPACE] New hand [+/-] Bet [Q] Quit".to_string() | 100 | "[SPACE] New hand [+/-] Bet [Q] Quit".to_string() |
| @@ -142,7 +143,7 @@ impl Game for BlackjackGame { | |||
| 142 | D - double (when available)\n\ | 143 | D - double (when available)\n\ |
| 143 | SPACE - deal a new hand\n\ | 144 | SPACE - deal a new hand\n\ |
| 144 | +/- - change the next hand's bet\n\ | 145 | +/- - change the next hand's bet\n\ |
| 145 | Q - leave the table" | 146 | Q - forfeit an active hand (bet is lost), or leave when no hand is active" |
| 146 | .to_string() | 147 | .to_string() |
| 147 | } | 148 | } |
| 148 | } | 149 | } |
diff --git a/src/server/core.rs b/src/server/core.rs index cf8c4b9..259f936 100644 --- a/src/server/core.rs +++ b/src/server/core.rs | |||
| @@ -297,11 +297,27 @@ impl ServerCore { | |||
| 297 | return format!("ERROR {error}"); | 297 | return format!("ERROR {error}"); |
| 298 | } | 298 | } |
| 299 | } | 299 | } |
| 300 | "cancel" => { | 300 | "forfeit" | "cancel" => { |
| 301 | let refund = session.bet_amount as i64; | 301 | hand.forfeit(); |
| 302 | let balance = database::credit(&mut self.conn, user, refund).unwrap_or(balance); | 302 | let state = hand.state(session_id, balance); |
| 303 | let details = serde_json::to_string(&state).unwrap_or_else(|_| "{}".to_string()); | ||
| 304 | let balance = match database::settle_play( | ||
| 305 | &mut self.conn, | ||
| 306 | session_id, | ||
| 307 | user, | ||
| 308 | "blackjack", | ||
| 309 | hand.bet as i64, | ||
| 310 | 0, | ||
| 311 | &details, | ||
| 312 | ) { | ||
| 313 | Ok(balance) => balance, | ||
| 314 | Err(error) => { | ||
| 315 | eprintln!("Blackjack forfeit settlement failed for {user}: {error}"); | ||
| 316 | let _ = self.sessions.remove_session(session_id); | ||
| 317 | return "ERROR Failed to update balance".to_string(); | ||
| 318 | } | ||
| 319 | }; | ||
| 303 | let _ = self.sessions.remove_session(session_id); | 320 | let _ = self.sessions.remove_session(session_id); |
| 304 | hand.cancel(); | ||
| 305 | let state = hand.state(session_id, balance); | 321 | let state = hand.state(session_id, balance); |
| 306 | return blackjack_wire(&state); | 322 | return blackjack_wire(&state); |
| 307 | } | 323 | } |
| @@ -485,7 +501,31 @@ impl ServerCore { | |||
| 485 | if let Some(user) = state.user.as_deref() { | 501 | if let Some(user) = state.user.as_deref() { |
| 486 | for session in self.sessions.get_user_sessions(user) { | 502 | for session in self.sessions.get_user_sessions(user) { |
| 487 | if session.game_type == "blackjack" { | 503 | if session.game_type == "blackjack" { |
| 488 | let _ = database::credit(&mut self.conn, user, session.bet_amount as i64); | 504 | if let Some(raw) = session.state.data.get("hand") { |
| 505 | if let Ok(mut hand) = BlackjackHand::from_json(raw) { | ||
| 506 | if !hand.is_done() { | ||
| 507 | hand.forfeit(); | ||
| 508 | let balance = | ||
| 509 | database::get_balance(&self.conn, user).unwrap_or(0); | ||
| 510 | let final_state = hand.state(&session.session_id, balance); | ||
| 511 | let details = serde_json::to_string(&final_state) | ||
| 512 | .unwrap_or_else(|_| "{}".to_string()); | ||
| 513 | if let Err(error) = database::settle_play( | ||
| 514 | &mut self.conn, | ||
| 515 | &session.session_id, | ||
| 516 | user, | ||
| 517 | "blackjack", | ||
| 518 | hand.bet as i64, | ||
| 519 | 0, | ||
| 520 | &details, | ||
| 521 | ) { | ||
| 522 | eprintln!( | ||
| 523 | "Blackjack disconnect forfeit failed for {user}: {error}" | ||
| 524 | ); | ||
| 525 | } | ||
| 526 | } | ||
| 527 | } | ||
| 528 | } | ||
| 489 | } | 529 | } |
| 490 | let _ = self.sessions.remove_session(&session.session_id); | 530 | let _ = self.sessions.remove_session(&session.session_id); |
| 491 | } | 531 | } |
diff --git a/src/server/games/blackjack.rs b/src/server/games/blackjack.rs index 9505fed..df5a6ac 100644 --- a/src/server/games/blackjack.rs +++ b/src/server/games/blackjack.rs | |||
| @@ -133,9 +133,9 @@ impl BlackjackHand { | |||
| 133 | Ok(()) | 133 | Ok(()) |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | pub fn cancel(&mut self) { | 136 | pub fn forfeit(&mut self) { |
| 137 | self.phase = "done".to_string(); | 137 | self.phase = "done".to_string(); |
| 138 | self.result = "cancelled".to_string(); | 138 | self.result = "forfeit".to_string(); |
| 139 | self.winnings = 0; | 139 | self.winnings = 0; |
| 140 | } | 140 | } |
| 141 | 141 | ||
