chironaut 0.3.5

A poker game library for Texas Hold'em and other poker variants
Documentation
use chironaut::{
    action::Action,
    game::Game,
    rules::GameRules,
    game::GameStage,
};

fn main() {
    println!("=== POSTFLOP MINIMUM RAISE TEST ===\n");
    
    // Create a No-Limit Hold'em game with 1/2 blinds
    let rules = GameRules::nlhe(1, 2);
    let mut game = Game::new(rules);

    // Add three players with 1000 chips each
    println!("Setting up 3 players with 1000 chips each");
    game.add_player_to_seat("Player 1".to_string(), 1000, 0).unwrap();
    game.add_player_to_seat("Player 2".to_string(), 1000, 1).unwrap();
    game.add_player_to_seat("Player 3".to_string(), 1000, 2).unwrap();
    
    // Start a hand
    match game.start_hand() {
        Ok(_) => {
            println!("Hand started successfully");
            
            // Show blinds and initial state
            println!("\nInitial state after blinds:");
            print_player_status(&game);
            println!("Pot: {}", game.pot);
            println!("Current bet: {}", game.current_bet);
            println!("Stage: {:?}", game.stage);
            
            // PREFLOP ACTION: Everyone calls
            
            // First player calls the big blind (2)
            println!("\nPREFLOP: Player 1 calls the big blind (2):");
            match game.handle_action(Action::Bet(2)) {
                Ok(_) => println!("  Call successful"),
                Err(e) => println!("  Error: {}", e),
            }
            
            // Second player calls
            println!("\nPREFLOP: Player 2 calls:");
            match game.handle_action(Action::Bet(2 - game.players[game.current_position].bet_amount)) {
                Ok(_) => println!("  Call successful"),
                Err(e) => println!("  Error: {}", e),
            }
            
            // Third player checks (they're the big blind)
            println!("\nPREFLOP: Player 3 checks:");
            match game.handle_action(Action::Bet(0)) {
                Ok(_) => println!("  Check successful"),
                Err(e) => println!("  Error: {}", e),
            }
            
            // Show state after preflop
            println!("\nState after preflop action:");
            print_player_status(&game);
            println!("Pot: {}", game.pot);
            println!("Current bet: {}", game.current_bet);
            println!("Stage: {:?}", game.stage);
            
            // FLOP ACTION: First player bets 77
            
            // Print current player to confirm we're at the expected position
            println!("\nCurrent position: {} ({})", 
                game.current_position, 
                game.players[game.current_position].name);
            
            // First player bets 77 on the flop
            println!("\nFLOP: Player 1 bets 77:");
            match game.handle_action(Action::Bet(77)) {
                Ok(_) => println!("  Bet successful"),
                Err(e) => println!("  Error: {}", e),
            }
            
            // Show state after bet
            println!("\nState after flop bet of 77:");
            print_player_status(&game);
            println!("Pot: {}", game.pot);
            println!("Current bet: {}", game.current_bet);
            
            // Print current player
            println!("\nCurrent position: {} ({})", 
                game.current_position, 
                game.players[game.current_position].name);
            
            // TEST 1: Second player tries to raise to 92 (which is less than min raise)
            println!("\nTEST 1: Player tries to raise to 92 (should fail - below min raise):");
            match game.handle_action(Action::Bet(92 - game.players[game.current_position].bet_amount)) {
                Ok(_) => println!("  ERROR: Raise was accepted but should have been rejected!"),
                Err(e) => println!("  Correctly rejected: {}", e),
            }
            
            // TEST 2: Second player raises to exactly the minimum (154)
            println!("\nTEST 2: Player raises to 154 (exactly min raise):");
            match game.handle_action(Action::Bet(154 - game.players[game.current_position].bet_amount)) {
                Ok(_) => println!("  Raise successful - correctly accepted the minimum"),
                Err(e) => println!("  ERROR: Raise was rejected but should have been accepted: {}", e),
            }
            
            // Show state after second raise
            println!("\nFinal state after valid raise:");
            print_player_status(&game);
            println!("Pot: {}", game.pot);
            println!("Current bet: {}", game.current_bet);
            
            // Explain the results
            println!("\n=== RESULTS EXPLANATION ===");
            println!("Postflop first bet: 77");
            println!("Attempted raise to 92 (raise size of only 15)");
            println!("Minimum raise to: 154 (77 + 77 = 154)");
            println!("The game correctly enforces the minimum raise rule on postflop betting.");
        },
        Err(e) => {
            println!("Error starting hand: {}", e);
        }
    }
}

fn print_player_status(game: &Game) {
    for (i, player) in game.players.iter().enumerate() {
        println!("Player {} ({})", i, player.name);
        println!("  Chips: {}", player.chips);
        println!("  Bet amount: {}", player.bet_amount);
        println!("  Folded: {}", player.is_folded);
        println!("  All-in: {}", player.is_all_in);
    }
}