chironaut 0.3.5

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

fn main() {
    println!("=== Street Transition Debug ===\n");
    
    // Create a 4-player No-Limit Hold'em game
    let rules = GameRules::nlhe(5, 10);
    let mut game = Game::new(rules);
    
    // Add players
    for i in 0..4 {
        game.add_player(format!("Player {}", i+1), 1000).unwrap();
    }
    
    // Start a hand
    println!("Starting hand...");
    game.start_hand().unwrap();
    
    // Play through the hand, printing debug info at each step
    println!("\n=== Preflop ===");
    process_preflop(&mut game);
    
    println!("\n=== Flop ===");
    process_street(&mut game, "flop");
    
    println!("\n=== Turn ===");
    process_street(&mut game, "turn");
    
    println!("\n=== River ===");
    process_street(&mut game, "river");
    
    println!("\n=== Showdown ===");
    assert_eq!(game.stage, GameStage::Showdown, "Game should be at showdown after river betting");
    println!("Final pot: ${}", game.pot);
    
    // Print final player stacks
    println!("\nFinal player stacks:");
    for (i, player) in game.players.iter().enumerate() {
        println!("Player {}: ${}", i+1, player.chips);
    }
    
    println!("\n=== TEST COMPLETE ===");
}

fn process_preflop(game: &mut Game) {
    // Print initial state
    print_game_state(game, "Before preflop betting");
    
    // First player calls
    println!("\nPlayer {} calls", game.current_position + 1);
    game.handle_action(Action::Bet(10)).unwrap();
    
    // Second player calls
    println!("Player {} calls", game.current_position + 1);
    game.handle_action(Action::Bet(10)).unwrap();
    
    // Small blind completes
    println!("Player {} calls", game.current_position + 1);
    game.handle_action(Action::Bet(5)).unwrap();
    
    // Big blind checks
    println!("Player {} checks", game.current_position + 1);
    game.handle_action(Action::Bet(0)).unwrap();
    
    // Check game state after preflop betting
    print_game_state(game, "After preflop betting");
    assert_eq!(game.stage, GameStage::Flop, "Game should advance to flop after preflop betting");
    println!("Community cards: {}", format_cards(&game.community_cards));
}

fn process_street(game: &mut Game, street_name: &str) {
    // Print initial state
    print_game_state(game, &format!("Before {} betting", street_name));
    
    // All players check except one who bets
    let bet_position = 1; // Second player bets
    
    for i in 0..4 {
        let current_pos = game.current_position;
        if i == bet_position {
            // One player bets
            println!("Player {} bets $20", current_pos + 1);
            game.handle_action(Action::Bet(20)).unwrap();
        } else {
            // Check or call
            if game.current_bet == 0 {
                println!("Player {} checks", current_pos + 1);
                game.handle_action(Action::Bet(0)).unwrap();
            } else {
                println!("Player {} calls $20", current_pos + 1);
                game.handle_action(Action::Bet(20)).unwrap();
            }
        }
    }
    
    // Check game state after betting
    print_game_state(game, &format!("After {} betting", street_name));
    
    // Determine expected next stage
    let expected_stage = match street_name {
        "flop" => GameStage::Turn,
        "turn" => GameStage::River,
        "river" => GameStage::Showdown,
        _ => panic!("Invalid street name"),
    };
    
    assert_eq!(game.stage, expected_stage, 
              "Game should advance to {:?} after {} betting", expected_stage, street_name);
    
    if street_name != "river" {
        println!("Community cards: {}", format_cards(&game.community_cards));
    }
}

fn print_game_state(game: &Game, description: &str) {
    println!("\n{}", description);
    println!("Game stage: {:?}", game.stage);
    println!("Current position: Player {}", game.current_position + 1);
    println!("Players acted: {:?}", game.players_acted.iter().map(|&p| p+1).collect::<Vec<_>>());
    println!("Is round complete: {}", game.is_round_complete());
    println!("Current bet: ${}", game.current_bet);
    println!("Pot: ${}", game.pot);
}

// Helper function to format cards for display
fn format_cards(cards: &[chironaut::card::Card]) -> String {
    cards.iter()
        .map(|card| card.to_string())
        .collect::<Vec<String>>()
        .join(", ")
}