ctm / mb2-doc

Mb2, poker software
https://devctm.com
7 stars 2 forks source link

Death due to stale alternate button #1383

Closed ctm closed 2 months ago

ctm commented 2 months ago

Find and fix the bug that caused this evening's game to panic:

thread '<unnamed>' panicked at mb2/src/table.rs:6200:49:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0:     0x5c8920337df6 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h410d4c66be4e37f9
   1:     0x5c8920363400 - core::fmt::write::he40921d4802ce2ac
   2:     0x5c8920334d0f - std::io::Write::write_fmt::h5de5a4e7037c9b20
   3:     0x5c8920337bd4 - std::sys_common::backtrace::print::h11c067a88e3bdb22
   4:     0x5c89203392d7 - std::panicking::default_hook::{{closure}}::h8c832ecb03fde8ea
   5:     0x5c8920339039 - std::panicking::default_hook::h1633e272b4150cf3
   6:     0x5c8920339768 - std::panicking::rust_panic_with_hook::hb164d19c0c1e71d4
   7:     0x5c8920339609 - std::panicking::begin_panic_handler::{{closure}}::h0369088c533c20e9
   8:     0x5c89203382f6 - std::sys_common::backtrace::__rust_end_short_backtrace::hc11d910daf35ac2e
   9:     0x5c8920339394 - rust_begin_unwind
  10:     0x5c891f93eb65 - core::panicking::panic_fmt::ha6effc2775a0749c
  11:     0x5c891f93ec23 - core::panicking::panic::h44790a89027c670f
  12:     0x5c891f93eab6 - core::option::unwrap_failed::hcb3a256a9f1ca882
  13:     0x5c891fde90ff - mb2::table::Table::blind_seat_at::h5821e80a45294a26
  14:     0x5c891fdfa02b - <mb2::table::Table as mb2::table::NextActions>::begin_hand_post_shuffle::h523325538c1ef726

My guess is this happened when smalltalkdan rejoined after a bust. My guess was wrong. This was due to Button having a small_blind field that we blindly trust is correct, which used to be true, but is no longer true with an alternate button.

ctm commented 2 months ago

I think this was event 5225.

ctm commented 2 months ago

The last public table message was:

mb2=> select id, received_at at time zone 'america/denver', message, table_id, player_id, hand_id from public_table_messages where id = 10740397;
    id    |          timezone          |               message               | table_id | player_id | hand_id 
----------+----------------------------+-------------------------------------+----------+-----------+---------
 10740397 | 2024-04-13 18:24:40.287423 | {"BigBlindAntes": [17, 400, false]} |     5790 |           |  400908
(1 row)

In the previous hand, smalltalkdan bust in a double board bomb pot, which means that the alternate button had been used for the hand that he bust, but the regular button was used on the hand that panicked.

The button is where we keep track of who had the small blind last, and although I haven't poked around in the database enough to be sure, most likely we simply aren't sanity checking it after switching between the alternate button and the regular button and vice-versa.

So, this is almost undoubtedly an "alternate button using" bug and trivial to reproduce and fix. In the meantime, only the wsop_2024_41_nlhe_plo_with_double_board_bomb_pot structure is affected, since it's the only structure where an alternate button is used.

ctm commented 2 months ago

I just now verified that indeed, smalltalkdan did have the big blind when he bust.

I also see that our alt-button is only to be used with games that don't have blinds, so the clean-up only needs to be done from when we switch into the regular button from either no button or the alt-button.

Now I'm wondering about mixes where we have games with no button and a button. Why haven't we seen this bug before? IOW, is mb2 already handling the case of the former big blind busting during a stud hand? If so, I should investigate using the same mechanism when switching from the alt-button. If not, then this bug is bigger than I thought.

ctm commented 2 months ago

Oops. Turns out, the rule that mb2 currently uses for switching from no button to button is to assign the small blind to the person to the left of the button, so a player can get lucky and post only the small blind if someone busts during a non-button using hand. As such, here's the fix:

diff --git a/mb2/src/table.rs b/mb2/src/table.rs
index 3e04c23e..2f8f9716 100644
--- a/mb2/src/table.rs
+++ b/mb2/src/table.rs
@@ -2214,11 +2214,7 @@ impl Table {

     fn collect_blinds(&mut self) {
         if !self.has_blinds() {
-            // If we're using the alternate button, then we don't want
-            // to change last_hand_used_button_and_blinds.
-            if !self.use_alt_button() {
-                self.last_hand_used_button_and_blinds = false;
-            }
+            self.last_hand_used_button_and_blinds = false;
             return;
         }
         self.last_hand_used_button_and_blinds = true;

Deploying now.