rustengine 1.0.60

Rust bitboard multi variant uci chess analysis engine.
Documentation
use crate::bitboard::*;
use crate::constants::*;
use crate::lineargame::*;
use crate::piece::*;
use crate::square::*;
//use crate::state::*;

use std::io::{self, BufRead};

pub struct Uci {
    pub engine_name: String,
    pub engine_author: String,
    pub linear_game: LinearGame,
}

pub fn create_default_uci() -> Uci {
    let mut uci = Uci {
        engine_name: "rustengine".to_string(),
        engine_author: "easychessanimations".to_string(),
        linear_game: LinearGame::new(),
    };
    uci.linear_game.init(DEFAULT_VARIANT);
    uci
}

pub fn demo() {
    let x: Bitboard = 0xffff00000000ffff;

    println!("{}", x.pretty_print_string());

    let sq: Square = rank_file(RANK_3, FILE_D);

    println!("square {} file {} rank {}", sq.uci(), sq.file(), sq.rank());

    let fig: Figure = LANCERNE;

    println!("\nfigure {} symbol {}", fig, fig.symbol());

    let p: Piece = color_figure(WHITE, LANCERNE);

    println!(
        "\npiece {} fen symbol {} san symbol {} uci symbol {} san letter {}",
        p,
        p.fen_symbol(),
        p.san_symbol(),
        p.uci_symbol(),
        p.san_letter()
    );

    let mut bb: Bitboard = sq.bitboard() | SQUARE_G6.bitboard();

    loop {
        println!("\n{}", bb.pretty_print_string());

        let (sq, ok) = bb.pop_square();

        if ok {
            println!("{}", sq.uci());
        } else {
            println!("no square could be popped\n");
            break;
        }
    }

    println!(
        "{}",
        jump_attack(SQUARE_E4, &KNIGHT_DELTAS, SQUARE_F6.bitboard()).pretty_print_string()
    );

    println!(
        "{}",
        sliding_attack(SQUARE_E4, &QUEEN_DELTAS, SQUARE_G6.bitboard()).pretty_print_string()
    );

    println!("{}", BISHOP_ATTACK[SQUARE_C7].pretty_print_string());

    println!("{}", KING_AREA[SQUARE_G8].pretty_print_string());
}

pub fn enum_occup_demo() {
    let occup = BISHOP_ATTACK[SQUARE_C7];

    let mut mask: usize = 0;

    loop {
        if mask < occup.variation_count() {
            println!(
                "{}\n{}",
                mask,
                translate_mask_to_occupancy(mask, occup).pretty_print_string()
            );
            mask += 1;
        } else {
            break;
        }
    }
}

pub fn mobility_demo() {
    println!(
        "{}",
        queen_mobility(
            SQUARE_E4,
            MoveGenMode::All,
            SQUARE_G6.bitboard() | SQUARE_C4.bitboard(),
            SQUARE_D5.bitboard() | SQUARE_E7.bitboard()
        )
        .pretty_print_string()
    )
}

pub fn magic_space() {
    let tb = total_magic_space(BISHOP_MAGICS);

    let sb = tb * std::mem::size_of::<Bitboard>();

    println!("total bishop magic space {} bytes", sb);

    let tr = total_magic_space(ROOK_MAGICS);

    let sr = tr * std::mem::size_of::<Bitboard>();

    println!("total rook magic space {} bytes", sr);

    println!(
        "\ngrand total magic space {} bytes = {:0.2} MiBs",
        sb + sr,
        (sb + sr) as f32 / 1e6
    );

    println!("magic units bishop {} rook {} total {}", tb, tr, tb + tr);
}

impl Uci {
    pub fn execute_uci_command(&self) {
        println!("id name {}", self.engine_name);
        println!("id author {}\n", self.engine_author);
        println!("uciok");
    }

    pub fn process_uci_command(&mut self, line: String) -> bool {
        let parts: Vec<&str> = line.split(" ").collect();

        let command = parts[0];

        if command == "quit" || command == "q" || command == "exit" || command == "x" {
            return false;
        }

        if command == "uci" {
            self.execute_uci_command();
            return true;
        }

        if command == "i" {
            self.linear_game.print();
            return true;
        }

        if command == "demo" {
            let mut arg = "";

            if parts.len() > 0 {
                arg = parts[1];
            }

            match arg {
                "occup" => enum_occup_demo(),
                "mob" => mobility_demo(),
                "space" => magic_space(),
                _ => demo(),
            }

            return true;
        }

        if command == "perft" || command == "p" {
            let depth = if command == "p" {
                4
            } else {
                parts[1].parse().expect("illegal perft depth")
            };
            let perft_result = self.linear_game.perft(depth);

            println!(
                "node(s) {:?} , time {:.2} sec(s) , nps {} kNode(s)/sec",
                perft_result.0, perft_result.1, perft_result.2
            );
        }

        if command == "bb" {
            self.linear_game.current().print_bitboards();

            return true;
        }

        if command == "d" {
            self.linear_game.pop();
            self.linear_game.print();
        }

        match command.parse::<usize>() {
            Ok(n) => {
                if n > 0 {
                    self.linear_game.push_by_index(n - 1);
                    self.linear_game.print();
                }
                return true;
            }
            Err(_) => (),
        }

        true
    }

    pub fn welcome(&self, build_info: &str) {
        println!(
            "{} bitboard multi variant uci chess analysis engine by {} [ {} ]",
            self.engine_name, self.engine_author, build_info
        );
    }

    pub fn uci_loop(&mut self) {
        let stdin = io::stdin();

        for line in stdin.lock().lines() {
            if !self.process_uci_command(line.unwrap()) {
                break;
            }
        }
    }
}