├── .github ├── dependabot.yml └── workflows │ └── rust.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── benches └── littlewing.rs ├── src ├── attack.rs ├── bitboard.rs ├── board.rs ├── clock.rs ├── color.rs ├── common.rs ├── dumb7fill.rs ├── eval.rs ├── fen.rs ├── game.rs ├── hyperbola.rs ├── lib.rs ├── main.rs ├── pgn.rs ├── piece.rs ├── piece_move.rs ├── piece_move_generator.rs ├── piece_move_list.rs ├── piece_move_notation.rs ├── piece_square_table.rs ├── positions.rs ├── protocols │ ├── cli.rs │ ├── mod.rs │ ├── uci.rs │ └── xboard.rs ├── search.rs ├── square.rs ├── transposition.rs ├── transposition_table.rs └── zobrist.rs └── tests ├── fool.pgn ├── perftsuite.epd ├── wac.epd ├── wac.rs └── zukertort_vs_steinitz_1886.pgn /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | on: [push] 3 | env: 4 | CARGO_TERM_COLOR: always 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/cache@v2 11 | with: 12 | path: | 13 | ~/.cargo/registry 14 | ~/.cargo/git 15 | target 16 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 17 | - run: cargo build --verbose 18 | - run: cargo test --verbose 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Cargo.lock 2 | /target 3 | /release 4 | TODO.md 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | ### 0.7.0 (2021-08-21) 6 | ### Fixed 7 | - Fix getopts parsing (#75) 8 | ### Added 9 | - Add `no_std` support to lib (#81) 10 | - Add chess prelude to lib (#82) 11 | ### Changed 12 | - Increase search reductions (#47) 13 | - Speed up large transposition table creations (#48) 14 | - Used std::time instead of time (#49) 15 | - Upgrade dependencies (#58) 16 | - Migrate from TravisCI to GitHub Actions (#66) 17 | - Upgrade to GitHub-native Dependabot (#72) 18 | - Update colored requirement from 1.9.3 to 2.0.0 (#60) 19 | 20 | ## 0.6.0 (2019-12-22) 21 | ### Fixed 22 | - Fix castling right update bug 23 | - Fix pawn move disambiguation in SAN 24 | - Fix white pieces color with black on white terminals in CLI 25 | - Avoid panicking in CLI 26 | ### Added 27 | - Add makefile 28 | - Parse moves in SAN format (#41) 29 | - Add `go movetime` command to UCI (#40) 30 | - Add `load pgn` and `save pgn` commands to CLI (#42) 31 | - Add `play none` subcommand to CLI 32 | - Add `init` command to CLI 33 | - Add command history file to CLI (#38) 34 | - Add autocompletion to CLI (#36) 35 | ### Changed 36 | - Increase futility pruning depth (#44) 37 | - Avoid TT cutoff on PV-nodes 38 | - Split PV over multiple lines in CLI mode (#45) 39 | - Add error propagation to CLI commands (#43) 40 | - Improve colors in CLI 41 | - Refactor board drawing 42 | - Update dependencies 43 | 44 | ## 0.5.0 (2018-07-18) 45 | ### Added 46 | - Use Hyperbola Quintessence and First Rank Attacks for sliding piece attacks 47 | - Use Xorshift random number generator for Zobrist hashing 48 | - Add depth parameter to `perft` CLI command 49 | - Add `save fen` and `save pgn` CLI commands 50 | - Add `--silent` flag to executable 51 | ### Changed 52 | - Improve CLI output 53 | - Rename `load` CLI command to `load fen` 54 | - Rename `Direction` to `Shift` and introduce a new (compass) `Direction` 55 | - Rename `Move*` to `PieceMove*` 56 | - Store castling rights in a u8 in `Position` 57 | - Use fail-soft instead of fail-hard in search 58 | - Refactor many parts of the code 59 | 60 | ## 0.4.0 (2017-11-20) 61 | ### Added 62 | - Add library with public API and documentation 63 | - Add getopt to parse program options 64 | - Add readline to user interface 65 | - Add piece square tables to evaluation 66 | - Add upper and lower bounds in transposition table 67 | - Add age field in transposition table 68 | - Add delta pruning to quiescence search 69 | - Add transposition table to quiescence search 70 | - Add basic UCI support 71 | - Add very basic parallel search in threads with shared transposition table 72 | ### Changed 73 | - Improve CLI 74 | - Improve statistics debug output 75 | - Refactor many parts of the code 76 | - Allow NMP, IID, and LMR at shallower depth 77 | - Set NMP R to 3 78 | 79 | ## 0.3.0 (2017-10-11) 80 | ### Added 81 | - Add principal variation search 82 | - Add internal iterative deepening 83 | - Add late move reduction 84 | - Add killer heuristic 85 | - Add basic null move pruning 86 | - Add basic futility pruning 87 | - Add basic mobility evaluation 88 | - Add static exchange evaluation 89 | ### Changed 90 | - Use static exchange evaluation in moves ordering 91 | - Skip bad captures in quiescence search 92 | 93 | ## 0.2.0 (2016-08-22) 94 | ### Added 95 | - Add basic quiescence search 96 | - Add basic transposition table 97 | - Add MVV/LVA moves ordering by insertion sort 98 | - Add staged moves generation 99 | - Add fullmoves and halfmoves counting 100 | - Add draw detection 101 | - Add mate pruning 102 | - Add XBoard `memory` command 103 | - Add `color` and `debug` command line flag 104 | ### Changed 105 | - Improve user interface 106 | - Display game result in XBoard 107 | - Save best move during iterative deepening 108 | - Print principal variation from transpositions table 109 | ### Fixed 110 | - Fix compiler warnings 111 | - Fix castling bug 112 | - Fix bug when undoing promotions 113 | 114 | ## 0.1.0 (2016-08-10) 115 | ### Changed 116 | - Improve time management 117 | ### Fixed 118 | - Fix compiler errors and warnings 119 | - Fix bug in search function 120 | - Fix promotion parsing bug 121 | 122 | ## 0.0.1 (2015-06-09) 123 | ### Added 124 | - Add bitboard moves generation with De Bruijn sequence 125 | - Add board array representation 126 | - Add basic evaluation 127 | - Add alpha beta pruning 128 | - Add iterative deepening 129 | - Add basic time management 130 | - Add support of XBoard protocol 131 | - Add Zobrist hashing 132 | - Add FEN support 133 | - Add `perft`, `perftsuite`, and `divide` commands in user interface 134 | - Add Travis CI 135 | 136 | ## 0.0.0 (2014-12-23) 137 | ### Added 138 | - Initial commit 139 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "littlewing" 3 | description = """ 4 | A chess engine rated at 2050+ ELO, compatible with both UCI and XBoard 5 | protocols, with a nice CLI, and a documented library. 6 | """ 7 | version = "0.7.0" 8 | license = "MIT" 9 | authors = ["Vincent Ollivier "] 10 | repository = "https://github.com/vinc/littlewing" 11 | homepage = "https://vinc.cc/software/littlewing" 12 | readme = "README.md" 13 | 14 | [lib] 15 | name = "littlewing" 16 | path = "src/lib.rs" 17 | 18 | [[bin]] 19 | name = "littlewing" 20 | path = "src/main.rs" 21 | doc = false 22 | 23 | [features] 24 | default = ["std", "bin"] 25 | std = ["dirs", "regex", "rustyline", "rustyline-derive", "no-std-compat/std"] 26 | bin = ["atty", "getopts"] 27 | 28 | [dependencies] 29 | atty = { version = "0.2.14", optional = true } 30 | dirs = { version = "4.0.0", optional = true } 31 | getopts = { version = "0.2.21", optional = true } 32 | lazy_static = "1.4.0" 33 | no-std-compat = { version = "0.4.1", features = ["alloc", "compat_macros"] } 34 | rand = { version = "0.8.5", default-features = false } 35 | rand_xorshift = { version = "0.3.0", default-features = false } 36 | regex = { version = "1.3.9", optional = true } 37 | rustyline = { version = "10.0.0", optional = true } 38 | rustyline-derive = { version = "0.7.0", optional = true } 39 | 40 | [badges] 41 | travis-ci = { repository = "vinc/littlewing" } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2023 Vincent Ollivier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: setup build install clean cross 2 | .EXPORT_ALL_VARIABLES: 3 | 4 | PREFIX = /usr/local 5 | LITTLEWING_VERSION = $(shell git describe) 6 | build: RUSTFLAGS = -C target-cpu=native 7 | 8 | build: 9 | cargo build --release 10 | 11 | setup: 12 | curl https://sh.rustup.rs -sSf | sh 13 | rustup update 14 | 15 | install: 16 | cp target/release/littlewing $(PREFIX)/bin 17 | 18 | uninstall: 19 | rm -f $(PREFIX)/bin/littlewing 20 | 21 | clean: 22 | cargo clean 23 | 24 | release: 25 | mkdir -p release 26 | cp README.md release/README.txt 27 | cp LICENSE release/LICENSE.txt 28 | cp CHANGELOG.md release/CHANGELOG.txt 29 | cross build --release --target x86_64-unknown-linux-gnu 30 | cross build --release --target x86_64-pc-windows-gnu 31 | cross build --release --target armv7-linux-androideabi 32 | cp target/x86_64-unknown-linux-gnu/release/littlewing release/littlewing-$(LITTLEWING_VERSION)-linux-x86 33 | cp target/armv7-linux-androideabi/release/littlewing release/littlewing-$(LITTLEWING_VERSION)-android-armv7 34 | cp target/x86_64-pc-windows-gnu/release/littlewing.exe release/littlewing-$(LITTLEWING_VERSION)-windows-x86.exe 35 | gzip release/littlewing-* 36 | cd release && shasum littlewing-* > shasums.txt 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Little Wing: a chess engine written in Rust 2 | =========================================== 3 | 4 | [![Travis](https://img.shields.io/travis/vinc/littlewing/master.svg)](https://travis-ci.org/vinc/littlewing/branches) 5 | [![Crates.io](https://img.shields.io/crates/v/littlewing.svg)](https://crates.io/crates/littlewing) 6 | 7 | Little Wing is the successor of [Purple Haze](https://github.com/vinc/purplehaze). 8 | 9 | The project started in December 2014 to learn the Rust language and play with 10 | bitboards. Both experiments were conclusive and Little Wing it is still 11 | maintained in 2023. 12 | 13 | Currently evaluated at around 2200 ELO on CCRL 40/4 Rating List. 14 | 15 | [![asciicast](https://asciinema.org/a/146112.png)](https://asciinema.org/a/146112) 16 | 17 | 18 | Features 19 | -------- 20 | 21 | - Interfaces 22 | - A nice CLI with many commands 23 | - XBoard and UCI communication protocols 24 | - Public API with [documented library](https://docs.rs/littlewing) 25 | - Board representation 26 | - Bitboard with LLVM CTPOP and CTTZ 27 | - Sliding piece attacks with Hyperbola Quintessence and First Rank Attacks 28 | - Zobrist hashing with Xorshift RNG 29 | - Staged moves generation 30 | - MVV/LVA and SEE moves ordering with insertion sort 31 | - FEN support 32 | - Search 33 | - Principal variation search 34 | - Quiescence search 35 | - Transposition table 36 | - Null move pruning 37 | - Internal iterative deepening 38 | - Futility pruning 39 | - Late move reduction 40 | - Killer heuristic 41 | - Evaluation 42 | - Piece square table evaluation 43 | - Mobility evaluation 44 | - Static exchange evaluation 45 | 46 | 47 | Install 48 | ------- 49 | 50 | Binaries for GNU/Linux (x86-64), Android (ARMv7), and Windows (x86-64) are 51 | available: https://vinc.cc/binaries 52 | 53 | If you want to compile Little Wing yourself, you must first install Rust: 54 | 55 | $ curl https://sh.rustup.rs -sSf | sh 56 | 57 | Then you can install the latest stable version of the engine with Cargo: 58 | 59 | $ cargo install littlewing 60 | 61 | Or the development version by fetching the git repository: 62 | 63 | $ git clone https://github.com/vinc/littlewing.git 64 | $ cd littlewing 65 | $ export RUSTFLAGS="-C target-cpu=native" 66 | $ export LITTLEWING_VERSION="$(git describe)" 67 | $ cargo build --release 68 | $ sudo cp target/release/littlewing /usr/local/bin 69 | 70 | 71 | Usage 72 | ----- 73 | 74 | Little Wing is compatible with XBoard and UCI communication protocols, 75 | and in addition it has its own text-based user interface: 76 | 77 | $ littlewing 78 | _,; 79 | , .--. _,-'.-; 80 | \`-, <) o `._ ,-' ,'`_7 81 | <_ `-\ _ _,' _.' 82 | <_`".| `\ ` _.> 83 | <_ ; \ _> 84 | `" ; `` 85 | Little Wing v0.7.0 \ | \ 86 | '|-. _ \ 87 | by Vincent Ollivier _/ / \ '. 88 | +---+---+---+---+---+"-"`---+--'\_> 89 | | r | n | b | q | k | b | n | r | 8 90 | +---+---+---+---+---+---+---+---+ 91 | | p | p | p | p | p | p | p | p | 7 92 | +---+---+---+---+---+---+---+---+ 93 | | | | | | | | | | 6 94 | +---+---+---+---+---+---+---+---+ 95 | | | | | | | | | | 5 96 | +---+---+---+---+---+---+---+---+ 97 | | | | | | | | | | 4 98 | +---+---+---+---+---+---+---+---+ 99 | | | | | | | | | | 3 100 | +---+---+---+---+---+---+---+---+ 101 | | P | P | P | P | P | P | P | P | 2 102 | +---+---+---+---+---+---+---+---+ 103 | | R | N | B | Q | K | B | N | R | 1 104 | +---+---+---+---+---+---+---+---+ 105 | a b c d e f g h 106 | 107 | > move e4 108 | 109 | +---+---+---+---+---+---+---+---+ 110 | | r | n | b | q | k | b | n | r | 8 111 | +---+---+---+---+---+---+---+---+ 112 | | p | p | p | p | p | p | p | p | 7 113 | +---+---+---+---+---+---+---+---+ 114 | | | | | | | | | | 6 115 | +---+---+---+---+---+---+---+---+ 116 | | | | | | | | | | 5 117 | +---+---+---+---+---+---+---+---+ 118 | | | | | | P | | | | 4 119 | +---+---+---+---+---+---+---+---+ 120 | | | | | | | | | | 3 121 | +---+---+---+---+---+---+---+---+ 122 | | P | P | P | P | | P | P | P | 2 123 | +---+---+---+---+---+---+---+---+ 124 | | R | N | B | Q | K | B | N | R | 1 125 | +---+---+---+---+---+---+---+---+ 126 | a b c d e f g h 127 | 128 | > time 1 10 129 | > show think 130 | > play black 131 | 132 | ply score time nodes pv 133 | 1 -46 0 1 1. ... a6 134 | 1 -45 0 3 1. ... c6 135 | 1 -22 0 4 1. ... d6 136 | 1 -20 0 5 1. ... e6 137 | 1 -1 0 14 1. ... d5 138 | 1 0 0 15 1. ... e5 139 | 1 9 0 20 1. ... Nc6 140 | 2 -47 0 53 1. ... Nc6 2. Nc3 141 | 3 9 0 278 1. ... Nc6 2. Nc3 Nf6 142 | 4 -45 0 860 1. ... Nc6 2. Nc3 Nf6 3. Nf3 143 | 4 -31 1 2437 1. ... d5 2. exd5 Qxd5 3. Nc3 144 | 5 -32 1 4647 1. ... d5 2. exd5 Qxd5 3. Nc3 Qd4 145 | 5 -20 2 7442 1. ... d6 2. Nc3 Nf6 3. Nf3 Nc6 146 | 5 0 2 11381 1. ... e5 2. Nc3 Nf6 3. Nf3 Nc6 147 | 5 1 2 12946 1. ... Nc6 2. Nc3 Nf6 3. Nf3 d5 148 | 6 -21 3 14052 1. ... Nc6 2. Nc3 Nf6 3. Nf3 d5 4. d3 149 | 7 -7 6 34813 1. ... Nc6 2. Nf3 Nf6 3. e5 Ng4 4. d4 d5 150 | 8 -29 9 53113 1. ... Nc6 2. Nf3 Nf6 3. e5 Ng4 4. d4 d6 151 | 5. h3 152 | 9 -25 27 181431 1. ... Nc6 2. d4 d5 3. e5 e6 4. Nc3 Bb4 153 | 5. Nf3 Nge7 154 | 9 -12 35 241217 1. ... e5 2. Nc3 Nf6 3. Nf3 Nc6 4. d4 exd4 155 | 5. Nxd4 d5 156 | 10 -10 50 363028 1. ... e5 2. Nc3 Nf6 3. Nf3 Nc6 4. d4 exd4 157 | 5. Nxd4 d5 6. f3 158 | 11 -7 109 815399 1. ... e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc4 Nxe4 159 | 5. d3 Nf6 6. Nc3 Nc6 160 | 12 -23 218 1686098 1. ... e5 2. Nf3 Nf6 3. Nc3 Nc6 4. d4 exd4 161 | 5. Nxd4 d5 6. exd5 Nxd5 7. Bc4 162 | 13 -13 467 3791367 1. ... e5 2. Nf3 Nf6 3. Nc3 Nc6 4. d4 exd4 163 | 5. Nxd4 d5 6. exd5 Nxd5 7. Bc4 164 | 165 | < move e5 166 | 167 | +---+---+---+---+---+---+---+---+ 168 | | r | n | b | q | k | b | n | r | 8 169 | +---+---+---+---+---+---+---+---+ 170 | | p | p | p | p | | p | p | p | 7 171 | +---+---+---+---+---+---+---+---+ 172 | | | | | | | | | | 6 173 | +---+---+---+---+---+---+---+---+ 174 | | | | | | p | | | | 5 175 | +---+---+---+---+---+---+---+---+ 176 | | | | | | P | | | | 4 177 | +---+---+---+---+---+---+---+---+ 178 | | | | | | | | | | 3 179 | +---+---+---+---+---+---+---+---+ 180 | | P | P | P | P | | P | P | P | 2 181 | +---+---+---+---+---+---+---+---+ 182 | | R | N | B | Q | K | B | N | R | 1 183 | +---+---+---+---+---+---+---+---+ 184 | a b c d e f g h 185 | 186 | > help 187 | 188 | Commands: 189 | 190 | quit Exit this program 191 | help Display this screen 192 | load [] Load game from 193 | save [] Save game to 194 | hint Search the best move 195 | play [] Search and play [] move[s] 196 | undo Undo the last move 197 | move Play on the board 198 | 199 | show Show 200 | hide Hide 201 | time