# Echecs
**A high-performance Chess Engine implemented in pure Elixir.**
[](https://github.com/HEKPYTO/ECHECS/actions/workflows/ci.yml)
Echecs is a robust chess library designed for speed and correctness. It leverages advanced optimization techniques available on the BEAM virtual machine (Bitboards, Magic Bitboards, Integer packing, etc), making it suitable for high-throughput analysis and scalable applications.
## Features
* **High Performance**: Process over **4,000 games per second** (benchmarked on M1 Pro).
* **Pure Elixir**: No NIFs or external dependencies (C/Rust) required for core logic.
* **Advanced Engine Architecture**:
* **Bitboards**: 64-bit integer representation for O(1) board operations.
* **Magic Bitboards**: Fast sliding piece attack generation.
* **Integer Move Encoding**: Zero-allocation move generation using packed 20-bit integers to minimize Garbage Collection.
* **Zobrist Hashing**: Efficient game state hashing for repetition detection.
* **Standard Compliance**:
* **FEN**: Full Forsyth-Edwards Notation parsing and generation.
* **PGN**: Parsing and replay support for standard chess games.
* **Complete Rule Implementation**: Castling, En Passant, Promotion, 50-move rule, and 3-fold repetition.
## Installation
Add `echecs` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:echecs, "~> 0.1.4"}
]
end
```
## Quick Start
### Basic Game Loop
```elixir
game = Echecs.new_game()
moves = Echecs.legal_moves(game)
from = Echecs.Board.to_index("e2")
to = Echecs.Board.to_index("e4")
{:ok, game} = Echecs.make_move(game, from, to)
Echecs.status(game)
```
Squares are 0-indexed from `a8 = 0` through `h1 = 63`.
### FEN Manipulation
```elixir
game = Echecs.new_game("rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2")
Echecs.FEN.to_string(game)
```
### PGN Parsing
```elixir
pgn = "1. e4 e5 2. Nf3 Nc6 3. Bb5"
moves = Echecs.PGN.parse_moves(pgn)
final_game = Echecs.PGN.replay(Echecs.new_game(), moves)
```
## Advanced Usage
### Performance Considerations
Echecs is designed to be extremely memory-efficient. The `Echecs.MoveGen.legal_moves_int/1` function returns moves as packed integers instead of structs, which is ideal for tight loops or search algorithms (e.g. Minimax) where struct allocation overhead is significant.
### Internal Board Representation
The board is represented internally as a Tuple of integers (Bitboards) for maximum access speed on the BEAM. This allows the engine to query piece locations and attack maps in constant time.
## Testing & Benchmarks
The engine is verified against large-scale replay validation from the Lichess database to ensure correctness and stability.
### Run Unit Tests
```bash
mix test
```
### Run Integration Benchmark
To verify large-scale replay correctness on your machine:
```bash
LICHESS_DB_PATH=path/to/file.pgn.zst mix test --include integration test/integration/lichess_db_test.exs
```
### Run Engine Benchmarks
```bash
mix echecs.benchmark
```
### Regenerate the Magic Cache
```bash
elixir scripts/generate_magic_cache.exs
```
## Docker Support
Deploy or test in a consistent environment using the provided Docker image. The image automatically pre-generates the magic bitboard cache for faster startup.
```bash
docker build -t echecs .
docker run -it --rm echecs
iex> Echecs.new_game()
```