Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
982 changes: 5 additions & 977 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ edition = "2021"
[dependencies]
async-std = "1.12.0"
chess = "3.2"
chess-tui = "1.6.1"
119 changes: 117 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
# Chess-AI-Rust
# Chess AI Rust

My [Chess-AI](https://github.com/mehulrao/Chess-AI/tree/main) Rewritten in Rust
A chess AI engine implemented in Rust with UCI (Universal Chess Interface) support.

## Features

- **Minimax Search Algorithm** with alpha-beta pruning
- **Iterative Deepening** for time-controlled searches
- **Transposition Tables** for move caching and optimization
- **Move Ordering** for better search efficiency
- **UCI Protocol Support** - Compatible with any UCI chess interface
- **Interactive Mode** - Play directly in the terminal

## UCI Mode

The engine supports the Universal Chess Interface (UCI) protocol, making it compatible with popular chess GUIs and analysis tools.

### Usage

To run the engine in UCI mode:

```bash
cargo run --release -- uci
```

### Compatible Software

The engine works with any UCI-compatible chess software, including:

- **chess-tui** - Terminal-based chess interface
- **Arena** - Chess GUI
- **ChessBase** - Professional chess software
- **Lichess** - Online chess platform (analysis)
- **cutechess-cli** - Command-line tournament manager

### Using with chess-tui

1. Build the engine:
```bash
cargo build --release
```

2. Run chess-tui with your engine:
```bash
chess-tui -e ./target/release/chess_ai_rust
```

### UCI Commands Supported

- `uci` - Initialize UCI mode
- `isready` - Check if engine is ready
- `ucinewgame` - Start a new game
- `position [fen <fen> | startpos] moves <move1> <move2> ...` - Set position
- `go [depth <d>] [movetime <ms>] [wtime <ms>] [btime <ms>] [winc <ms>] [binc <ms>]` - Start searching
- `stop` - Stop current search
- `setoption name <name> value <value>` - Set engine options
- `quit` - Exit the engine

### Engine Options

- **Hash** - Transposition table size in MB (default: 64, range: 1-1024)
- **MaxDepth** - Maximum search depth (default: 10, range: 1-100)
- **UseSecondSearch** - Enable quiescence search (default: true)

## Interactive Mode

To play directly in the terminal:

```bash
cargo run --release
```

This mode provides a simple text-based interface for playing against the AI.

## Building

```bash
cargo build --release
```

## Testing

To test the UCI implementation:

```bash
# Start the engine in UCI mode
cargo run --release -- uci

# Send UCI commands manually:
# uci
# isready
# position startpos moves e2e4
# go depth 5
# quit
```

## Performance

The engine uses several optimization techniques:

- **Alpha-beta pruning** - Reduces search tree size
- **Iterative deepening** - Provides anytime results
- **Transposition tables** - Avoids re-computing positions
- **Move ordering** - Improves pruning efficiency
- **Quiescence search** - Handles tactical positions

## Architecture

- `src/main.rs` - Mode selection and interactive interface
- `src/uci/` - UCI protocol implementation
- `src/searcher.rs` - Search algorithm implementation
- `src/evaluation.rs` - Position evaluation
- `src/move_ordering.rs` - Move ordering heuristics
- `src/entry.rs` - Transposition table entries

## License

This project is licensed under the MIT License.
76 changes: 76 additions & 0 deletions UCI_EXAMPLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# UCI Implementation Example

This chess engine now supports the Universal Chess Interface (UCI) protocol.

## Quick Start

1. **Build the engine:**
```bash
cargo build --release
```

2. **Run in UCI mode:**
```bash
cargo run --release -- uci
```

3. **Use with chess-tui:**
```bash
chess-tui -e ./target/release/chess_ai_rust
```

## Manual UCI Testing

You can test the UCI implementation manually:

```bash
# Start the engine
cargo run --release -- uci

# The engine will respond with:
# id name Chess AI Rust
# id author Chess AI Rust Developer
# option name Hash type spin default 64 min 1 max 1024
# option name MaxDepth type spin default 10 min 1 max 100
# option name UseSecondSearch type check default true
# uciok

# Now you can send commands:
isready
# readyok

position startpos moves e2e4
go depth 5
# info depth 1 score cp 23 nodes 45 time 1 pv d7d6
# info depth 2 score cp 18 nodes 127 time 3 pv d7d6
# ...
# bestmove d7d6

quit
```

## UCI Commands Supported

- `uci` - Initialize UCI mode
- `isready` - Check if engine is ready
- `ucinewgame` - Start a new game
- `position [fen <fen> | startpos] moves <moves>` - Set position
- `go [depth <d>] [movetime <ms>] [time controls...]` - Start searching
- `stop` - Stop current search
- `setoption name <name> value <value>` - Set engine options
- `quit` - Exit

## Engine Options

- **Hash**: Transposition table size in MB (1-1024, default: 64)
- **MaxDepth**: Maximum search depth (1-100, default: 10)
- **UseSecondSearch**: Enable quiescence search (true/false, default: true)

## Interactive Mode

The original interactive mode is still available:

```bash
cargo run --release
# (runs without UCI, direct terminal play)
```
83 changes: 4 additions & 79 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,85 +1,10 @@
use chess::{CacheTable, ChessMove, Color, Game};
mod searcher;
use crate::{entry::Entry, searcher::Searcher};
mod entry;
mod evaluation;
mod move_ordering;

const TARGET_DEPTH: usize = 5;
const PLAYER: Color = Color::White;
const TT_SIZE: usize = 67108864;
const TIME: u64 = 5000;
mod searcher;
mod uci;

fn main() {
let mut game = Game::new();
//let mut game = Game::from_str("r3kb1r/pqp1n1p1/2p1b2p/4Bp2/Q3p3/P1N4N/2P2PPP/3R1RK1 w kq - 0 1").unwrap();
if !game.result().is_none() {
println!("Mate!");
return;
}

let mut tt: CacheTable<Entry> = CacheTable::new(TT_SIZE, Entry::new_default());
println!("--------------------------------");
println!("{}", game.current_position());
while game.result().is_none() {
if PLAYER == Color::Black {
do_search(&mut game, &mut tt);
user_move(&mut game);
} else {
loop {
user_move(&mut game);
do_search(&mut game, &mut tt);
}
}
}
}

fn user_move(game: &mut Game) {
loop {
let mut move_text = String::new();
println!("Enter your move: ");
std::io::stdin().read_line(&mut move_text).unwrap();
if move_text.trim_end() == "O-O" {
if PLAYER == Color::White {
move_text = String::from("e1g1");
} else {
move_text = String::from("e8g8");
}
} else if move_text == "O-O-O" {
if PLAYER == Color::White {
move_text = String::from("e1c1");
} else {
move_text = String::from("e8c8");
}
}
let _move =
match ChessMove::from_san(&game.current_position(), &move_text.trim().to_string()) {
Ok(m) => {
game.make_move(m);
break;
}
Err(_) => {
println!("Invalid Move: {}", move_text);
continue;
}
};
}
println!("--------------------------------");
println!("{}", game.current_position());
}

fn do_search(game: &mut Game, tt: &mut CacheTable<Entry>) {
let mut searcher: Searcher = Searcher::new(game.current_position(), true);
searcher.do_iterative_deepening_search(TARGET_DEPTH, tt);

println!(
"Best Move: {}{}",
searcher.get_best_move().unwrap().get_source(),
searcher.get_best_move().unwrap().get_dest()
);
println!("Best Eval: {}", searcher.get_best_eval());
println!("TT Hits: {}", searcher.get_num_tt());
game.make_move(searcher.get_best_move().unwrap());
println!("--------------------------------");
println!("{}", game.current_position());
// Always run UCI mode
uci::run_uci_loop();
}
Loading