cliard24 0.1.2

cliard24 is a command-line 24-point card game. It provides two main functions: the game mode allows you to play the classic 24-point game interactively in the terminal, where you randomly draw 4 cards and use addition, subtraction, multiplication, division, and parentheses to reach 24; the solve mode lets you input any combination of numbers and a target value to calculate all possible expression solutions. The tool supports customizable attempt limits, endless mode, solution count limits, and mixed input of card letters (A/J/Q/K) and numbers.
Documentation
//! # Main Entry Point of cliard24
//!
//! This module serves as the entry point for the 24-point card game command-line application.
//! It handles command-line argument parsing using Clap and delegates to the appropriate game modes.
//!
//! The application supports two main modes:
//! - **Play Mode**: Interactive game where users solve 24-point puzzles
//! - **Solve Mode**: Solution finder for specific card combinations
//!
//! ## Usage
//! ```bash
//! # Interactive game mode
//! cliard24 play --max-attempts 3 --limit 1 --endless
//!
//! # Solver mode for specific numbers
//! cliard24 solve 3 8 6 1 --target 24 --limit 5
//! ```

use clap::{Parser, Subcommand};
use cliard24::{
    expression::ast::ExprNum,
    tui::{game_mode::run_game_mode, solve_mode::run_solver_mode},
};

/// Command-line interface parser for the 24-point card game
///
/// Uses Clap's derive macros to define the command-line structure and arguments.
/// When no subcommand is provided, defaults to interactive game mode.
#[derive(Parser, Debug)]
#[command(
    version,
    author = "Expien1",
    about = "cliard24 - A command-line 24-point card game with interactive play and expression solving capabilities.",
    long_about = "cliard24 is a command-line 24-point card game. \
    It provides two main functions: the game mode allows you to play the classic 24-point game interactively \
    in the terminal, where you randomly draw 4 cards and use addition, subtraction, multiplication, division, \
    and parentheses to reach 24; the solver mode lets you input any combination of numbers and a target value \
    to calculate all possible expression solutions. The tool supports customizable attempt limits, endless mode, \
    solution count limits, and mixed input of card letters (A/J/Q/K) and numbers."
)]
pub struct Cli {
    /// The game mode to execute (play or solve)
    #[command(subcommand)]
    pub mode: Option<Mode>,
}

/// Available game modes for the 24-point card game
///
/// This enum defines the two primary operational modes of the application:
/// - Interactive gameplay with configurable options
/// - Solution finding for specific number combinations
#[derive(Subcommand, Debug)]
pub enum Mode {
    /// Interactive 24-point game mode
    ///
    /// Starts an interactive session where players solve randomly generated
    /// 24-point puzzles with configurable difficulty and game rules.
    ///
    /// # Arguments
    /// * `max_attempts` - Maximum number of attempts allowed per round (0 for unlimited)
    /// * `limit` - Maximum number of solutions to find per round (0 for all solutions)
    /// * `endless` - Whether to enable continuous gameplay across multiple rounds
    ///
    /// # Examples
    /// ```bash
    /// # Start a game with 3 attempts per round, find 1 solution, in endless mode
    /// cliard24 play --max-attempts 3 --limit 1 --endless
    /// ```
    #[command(about = "Start a new interactive 24-point game")]
    Play {
        /// Maximum number of attempts per round (0 for unlimited)
        #[arg(short, long, default_value_t = 3)]
        max_attempts: u8,

        /// Limit the number of solutions to find per round (0 for all solutions)
        #[arg(short, long, default_value_t = 1)]
        limit: usize,

        /// Enable endless mode (game loops continuously through rounds)
        #[arg(short, long, default_value_t = false)]
        endless: bool,
    },

    /// Solution finder for specific number combinations
    ///
    /// Finds all valid arithmetic expressions that evaluate to the target value
    /// using the provided numbers exactly once each.
    ///
    /// # Arguments
    /// * `nums` - The operands required for the solution
    /// * `limit` - Maximum number of solutions to display (0 for all solutions)
    /// * `target` - The target numerical value to achieve
    ///
    /// # Examples
    /// ```bash
    /// # Find at most 5 solutions for numbers 3, 8, 6, 1 with target 24
    /// cliard24 solve 3 8 6 1 --target 24 --limit 5
    /// ```
    #[command(about = "Find solutions for specific card combinations")]
    Solve {
        /// The operands required for the solution, separated by spaces.
        #[arg(required = true, num_args = 2..)]
        nums: Vec<ExprNum>,

        /// Limit the number of solutions to find (0 for all solutions)
        #[arg(short, long, default_value_t = 0)]
        limit: usize,

        /// The target numerical value that needs to be solved.
        #[arg(short, long, default_value_t = 24.0)]
        target: ExprNum,
    },
}

/// Main entry point for the 24-point card game application
///
/// Parses command-line arguments and delegates to the appropriate game mode handler.
/// Defaults to interactive game mode when no subcommand is provided.
///
/// # Panics
///
/// This function may panic if:
/// - Command-line argument parsing fails
/// - The TUI components fail to initialize properly
/// - Underlying game logic encounters an unrecoverable error
///
/// # Examples
/// The main function is automatically called when the executable runs:
/// ```bash
/// ./cliard24 play --max-attempts 3
/// ```
fn main() {
    let cli = Cli::parse();

    match cli.mode {
        Some(Mode::Play {
            max_attempts,
            limit,
            endless,
        }) => {
            if endless {
                print_title("ENDLESS MODE");
            } else {
                print_title("WELCOME TO");
            }
            run_game_mode(max_attempts, limit, endless);
        }
        Some(Mode::Solve {
            nums,
            limit,
            target,
        }) => {
            print_title("SOLVE MODE");
            run_solver_mode(&nums, limit, target);
        }
        None => {
            // Default behavior when no subcommand is provided
            print_title(env!("CARGO_PKG_VERSION"));
            run_game_mode(3, 1, false);
        }
    };
}

/// Prints the ASCII art title with a customizable subtitle
///
/// # Arguments
///
/// * `sub_title` - The text to display on the right side of the title art
///
/// # Examples
/// ```
/// print_title("GAME MODE");
/// ```
fn print_title(sub_title: &str) {
    println!(
        r#"
  ____ _ _  {:>12} _ .------..------.
 / ___| (_) __ _ _ __ __| ||2.--. ||4.--. |
| |   | | |/ _` | '__/ _` || :/\: || (\/) |
| |___| | | (_| | | | (_| || (__) || :\/: |
 \____|_|_|\__,_|_|  \__,_|| '--'2|| '--'4|
  ---- - -  ---  --   ---  `------'`------'
  "#,
        sub_title
    );
}