connect-four-solver 0.2.4

A strong and perfect connect four solver in Rust
Documentation
use std::io::{stdin, stdout, self, BufRead};

use connect_four_solver::{ConnectFour, Solver};

fn main() -> io::Result<()>{
    println!("\
        Place a stone in the connect four board by typing the column number 1-7. Press s to
        calculate score of current position. Use `p` to pick the first best move.");

    let mut game = ConnectFour::new();
    let mut input = stdin().lock();
    let mut line = String::new();
    let mut solver = Solver::new();

    while !game.is_over() {
        game.print_to(stdout())?;

        line.clear();
        input.read_line(&mut line)?;
        let line = line.trim();
        if line == "s"{
            print_scores(game, &mut solver);
            continue;
        }
        if line == "p" {
            let mut best_moves = Vec::new();
            solver.best_moves(&game, &mut best_moves);
            if let Some(&col) = best_moves.first() {
                game.play(col);
            } else {
                println!("No legal moves left.");
            }
            continue;
        }
        if let Ok(col) = line.parse() {
            game.play(col);
        } else {
            println!("Invalid column.");
            continue;
        };
    }
    game.print_to(stdout())?;

    Ok(())
}

fn print_scores(game: ConnectFour, solver: &mut Solver) {
    for col in game.legal_moves() {
        let mut game_copy = game;
        if game_copy.play(col) {
            let score = solver.score(&game_copy);
            let stones_to_end = stones_to_end(game.stones() as i8, score);
            let result_msg = match score.signum() {
                0 => "Draw",
                1 => "Loss",
                -1 => "Win",
                _ => unreachable!()
            };
            println!("{col}: {result_msg} in {stones_to_end} stones.");
        }
    }
}

fn stones_to_end(current_turn: i8, score: i8) -> i8 {
    if score == 0 {
        return 42 - current_turn;
    }

    let remaining_stones_at_end = score.abs() - 1;
    let remaining_stones_now = 42 / 2 - current_turn / 2;
    let stones_for_winner_to_throw = remaining_stones_now - remaining_stones_at_end;
    if score.is_positive() {
        stones_for_winner_to_throw * 2
    } else {
        (stones_for_winner_to_throw - 1) * 2 + 1
    }
}