github.com/frankkopp/FrankyGo@v1.0.3/README.md (about) 1 # FrankyGo 2 Go implementation of a UCI compatible chess engine. 3 4 [![Build Status](https://travis-ci.org/frankkopp/FrankyGo.svg?branch=master)](https://travis-ci.org/frankkopp/FrankyGo) 5 [![codecov](https://codecov.io/gh/frankkopp/FrankyGo/branch/master/graph/badge.svg)](https://codecov.io/gh/frankkopp/FrankyGo) 6 [![Go Report Card](https://goreportcard.com/badge/github.com/frankkopp/FrankyGo)](https://goreportcard.com/report/github.com/frankkopp/FrankyGo) 7 [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/frankkopp/WorkerPool/blob/master/LICENSE) 8 9 ## Description 10 FrankyGo is the fourth chess engine I wrote. The first one was written in Java and had a JavaFX UI 11 ([Chessly](https://github.com/frankkopp/Chessly)) but did not support UCI. I was very inexperienced then, and the 12 engine itself was not good. But I learned a lot and also liked developing the JavaFx part. I then rewrote it in Java 13 again but as an UCI engine. This time the structure was much better thanks to many great chess engine developers I 14 learned from. I also found out that my interest is in actual programming rather than building the "best" chess engine. 15 Therefore, I used what I learned from other chess engines but tried to build mine in a clean and easy to understand way. 16 This resulted in Franky 1.0 17 ([Github](https://github.com/frankkopp/FrankyUCIChessEngine), 18 [CCRL](http://www.computerchess.org.uk/ccrl/404/cgi/engine_details.cgi?print=Details&each_game=1&eng=Franky%201.0%2064-bit#Franky_1_0_64-bit)) 19 20 I then started to re-write it in C++ ([FrankyCPP](https://github.com/frankkopp/FrankyCPP)) and came quite far. But C++ 21 (and its infrastructure) forced me to focus a lot on the language itself, and the surrounding tools. E.g. I learned a lot 22 (too much?) about different compilers on different platforms, CMake, Boost, Google Test, etc. but it rather distracted 23 me a lot from developing the chess engine itself. My time is limited so this was very annoying. 24 25 Then I looked into [Go](https://golang.org/doc/). A completely new language compiled directly into machine code, 26 platform independent, with a garbage collector and the promise to be as fast as C++/C. This was the motivation to start 27 FrankyGo and Go kept its promises. Easy to learn, great tool set, no distraction from the code by the language and 28 indeed fast. See below "Learning Go". 29 30 So FrankyGo is now a rather clean chess engine with a lot of potential. As mentioned above I do not claim to have 31 invented any of algorithms and in fact I used many ideas from Stockfish, Crafty, Beowulf, etc. See "Credits" below. 32 But I had a lot of fun developing it and I do hope to have more fun improving it in the future. 33 34 There is a small issue though - when developing a chess engine up to a certain level, testing starts to completely 35 overshadow development. Every feature, every evaluation, every change needs lots of testing against KPIs, test suites, 36 itself and real other engines. These tests are extremely time-consuming if they are to be meaningful. It needs thousands 37 of games to reliably prove that a feature is an improvement, and these games need time. Too short thinking times make 38 the tests unreliable, especially for features which have increased effect in deeper searches. So several computers 39 doing tests at the same time is normal but also rather stressful :) 40 41 I will go on improving FrankyGo, and I'm happy to receive any feedback on my Go code but also of course on improving 42 the engine itself. 43 44 A word on v1.0: I have implemented most major and common chess engine features, and the search itself is ok for now 45 but can of course always be improved. There are many great ideas out there to make it even more effective. Evaluation 46 in v1.0 is very basic. Only material and positional differences are counted. There are already some other evaluations 47 implemented but deactivated as they need a lot of testing and tuning. 48 49 ## Features (v1.0.0) 50 * UCI protocol (to use the engine in Arena, xboard, Fritz or other chess user interfaces) 51 * UCI Options 52 * UCI Search Modes 53 * FIDE compliant (move repetition, 50-moves rules, draw for low material) 54 * Board representation bitboards and 8x8 piece array 55 * Bitboards, Magic Bitboards, pre-computed bitboards and data 56 * Move Generation using bitboards 57 * all moves or on demand in phases 58 * mode: all, capture only, non capture, check evasions 59 * move sorting for estimated value of move, pv move and killer moves 60 * ~53 Million moves per sec on my i7-7700 61 * Perft tests 62 * ~4.8+Million nps 63 * Search as PVS AlphaBeta search 64 * all UCI search modes 65 * Iterative Deepening 66 * Pondering 67 * Quiescence 68 * SEE for deciding on good qsearch moves 69 * Internal Iterative Deepening 70 * Killer Moves 71 * History Pruning (History Count, Counter Move) 72 * Mate Distance Pruning 73 * Null Move Pruning 74 * Late Move Reductions (needs further tuning) 75 * Late Move Pruning (needs further tuning) 76 * Check extension (needs further tuning/testing) 77 * Mate threat extension (deactivated - needs further tuning/testing - currently weakens play) 78 * Reverse Futility Pruning (Static Null Move) 79 * Futility Pruning (also in quiescence search) 80 * Razoring (Stockfish like) 81 * History Pruning (History Count, Counter Moves) 82 * ~2.4 nps on average on i7-7700 and 256 MB hash 83 * TODO: Aspiration Windows, MTDf, Multi-cut Pruning, 84 * Transposition Table 85 * Opening Book from PGN, SAN and Simple move list files and persistent cache 86 * Evaluation 87 * Very simple yet: Material, positional piece values 88 * Implemented but not yet tested/activated: Attacks, Mobility, Piece specific evaluations 89 * TODO: pawn evaluations and pawn hash table 90 * Tests: 91 * Test framework to run EPD test suites 92 * Test to determine search tree size for features 93 * Test tool to run multiple test suites to test features 94 * General: 95 * logging, command lines options, configuration file, search and eval parameters in config files 96 97 * Open topics: 98 * Parallel search 99 100 ## Learning Go 101 Learning a new programming language is always most efficient within a real project. 102 As I have developed a chess engine in Java in the past and recently migrated it to C++ 103 I thought that implementing a chess engine in Go is a great opportunity to learn the language. 104 105 Chess engines offer a lot of different challenges in many aspects of a programming language. 106 E.g. efficient data types and data structures, high performance code where even nanoseconds count, reading 107 an opening book from files and creating a cache, bit twiddling, caches, recursion, unit testing, 108 performance testing and optimization, logging, configurations, communication with other processes over 109 pipes (UCI protocol), protocol implementation, etc. 110 111 Especially the high performance code is something I'm interested in. The usual advice in programming 112 is readability/understandability/maintainability of code is more important than performance and also, don't optimize 113 too early, etc. In chess there are some recurring hot spots in the algorithms, which need extra attention 114 on how they are implemented from the beginning, or they would be very slow. So a chess engine is a special 115 case where efficiency and performance has a higher priority than in a typical application. 116 117 E.g. a chess engine evaluates (calculating a numerical estimation of how "good" a position is) millions 118 of positions per second. For each position there are in average 35 moves to play. So to be able to search 119 a million positions per second you need to generate at least the same amount of moves - usually many more 120 as the alpha-beta search algorithm and other pruning techniques discard many positions before 121 they are even evaluated. 122 123 For evaluating 1 million positions per second you have a time budget of 1.000 nanoseconds for creating 124 the move that leads to this position, executing the move on your chess board data structure, evaluate 125 the position, and the many other things you need to do so that your chess engines has at least some 126 playing strength. So you see, nanoseconds matter. 127 128 As an example many years ago, during my first attempt at this in Java, it was quickly clear, that you can't model 129 all of your data types as Java objects. Especially a chess move would be too expensive when implemented 130 as a Java object as you need to create hundreds of millions in a very short time just to throw them away 131 quickly. Object creation and garbage collection made this approach extremely slow. So one of the first "optimizations" 132 I did was to use a plain integer to represent a move. With bit twiddling I encoded the necessary data into the 133 integer (from square, to square, move type, etc.). This is a very common approach in all the serious chess engines. 134 135 This example also shows a big difference between Java, C++ and Go. In Java, when implementing a move as an int you 136 loose type checking by the compiler. In C++ you have typedef and in Go you have something similar to typdef. With a 137 user defined primitive type the engine can use a plain int internally, but the compiler still can check the type 138 correctness for moves. This is one of my most missed features in Java. 139 140 What I already can say about Go is that implementing the chess engine in it was a joy and much easier done in Go than 141 in Java or C++. Of course, I have experience building a chess engine now but mostly I noticed that in Go I could focus 142 on the program itself and was rarely distracted by the "quirks" of the programming language although it was new to me. 143 I'm aware I did not follow many of Go's best practices but rather "transferred" my existing code from C++/Java to it. 144 Also, some aspects needed some re-thinking (e.g. no cyclic imports) but overall Go required much less language awareness 145 than for example C++ where I still find the compile-process unnecessary complicated (.h, cpp - declaration and 146 definition, etc.) or Java where I can't have user defined primitive types. 147 148 In addition to this all the tools included and standardized in Go are extremely valuable. I had so many headaches in 149 the past to find good free tools for Java and especially C++ for profiling, assembly code review, etc. comfortable on 150 all platforms I'm using (Windows, Mac, Linux). 151 Just look at this output from the Go pprof profiler which comes for free with Go: 152 153 ![pprof](https://github.com/frankkopp/FrankyGo/raw/master/docs/pprof_graph.png) 154 155 ## Installation 156 Windows build: 157 158 go build -o FrankyGo.exe github.com/frankkopp/FrankyGo/cmd/FrankyGo 159 160 Run FrankyGo.exe 161 162 Unix/Mac build: 163 164 go build -o FrankyGo github.com/frankkopp/FrankyGo/cmd/FrankyGo 165 166 Run FrankyGo 167 168 ## Usage 169 Typically, a UCI engine will be used with a UCI compatible chess interface like Arena, xboard, Fritz, etc. 170 Just configure a new engine in the UCI interface pointing to the executable of FrankyGo. If necessary use 171 command line options to find config file, logs folder and opening books folder. 172 173 To configure the engine (log level, search and evaluation features and parameters, etc.) a config file can be used. 174 Default place to look for it is ./config.toml. Use command line option "-config" to change the location. 175 176 Also helpful: 177 * logs files are stored in folder "../logs" or folder defined by cmd line option "-logpath" 178 * opening books are searched in folder "../assets/book" or folder defined in cmd line option "-bookpath" 179 180 Command line options: 181 182 ``` 183 Usage of D:\_DEV\go\src\github.com\frankkopp\FrankyGo\bin\FrankyGo.exe: 184 -bookFormat string 185 format of opening book 186 (Simple|San|Pgn) 187 -bookfile string 188 opening book file 189 provide path if file is not in same directory as executable 190 Please also provide bookFormat otherwise this will be ignored 191 -bookpath string 192 path to opening book files (default "../assets/books") 193 -config string 194 path to configuration settings file (default "./config.toml") 195 -fen string 196 fen for perft and nps test (default "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1") 197 -loglvl string 198 standard log level 199 (critical|error|warning|notice|info|debug) (default "info") 200 -logpath string 201 path where to write log files to (default "../logs") 202 -nps int 203 starts nodes per second test for given amount of seconds 204 -perft int 205 starts perft with the given depth 206 -searchloglvl string 207 search log level 208 (critical|error|warning|notice|info|debug) 209 -testdepth int 210 search depth limit for each test position 211 -testsuite string 212 path to file containing EPD tests or folder containing EPD files 213 -testtime int 214 search time for each test position in milliseconds (default 2000) 215 -version 216 prints version and exits 217 ``` 218 219 ## Roadmap 220 ### vx.x (planned) 221 - TODO: 222 - Aspiration 223 - MTDf 224 - Better Evaluation and testing 225 - Pawn Structure Cache 226 - MultiCut Pruning 227 - Other Prunings 228 - Continuously Performance/Profiling/Testing 229 - Tuning and Testing of all search features and parameters 230 231 ## Versions 232 233 ### v1.0.2 (done) 234 - FIX: 235 - Fixed a bug in pre computation of positional values. 236 237 ### v1.0.1 (done) 238 - FIX: 239 - MoveGen hasLegalMove did not check pawn doubles but necessary when pawn double blocks attacker in an otherwise near mate position. 240 241 ### v1.0.0 (done) 242 - DONE: 243 - change default behavior for log files so running the executable without logs folder works smoothly 244 - make it runnable without config file / config file optional 245 - Razor (Stockfish) 246 - QSearch Futility Pruning 247 - Additional Feature Test tool 248 - History Heuristics (History Counter, Counter Moves) 249 250 ### v0.8.0 (done) 251 - DONE 252 - SEE 253 - Move generation considering check evasion 254 - Reverse Futility Pruning 255 - Futility Pruning 256 - Search extensions: 257 - Check extension 258 - Mate threat extension (not active - search tree gets too big) 259 - Restructuring of packages to better match Go best practices 260 261 ### v0.7 (done) 262 - DONE 263 - LMP and LMR 264 - Null Move 265 - Use TestSuites, TreeSize and Arena to test features 266 - Better Evaluation (not active in config yet - needs testing) 267 - Performance/Profiling/Testing 268 - Removed MPP (Minor Promotion Pruning) - more harm than benefit 269 270 ### v0.6 (done) 271 - DONE 272 - Enhance TestSuite / run from command line options 273 - TestSuite Tests 274 - PVS 275 - Killer 276 - TT in QS 277 - MDP/MPP 278 279 ### v0.5 (done) 280 - DONE 281 - Use TT 282 - SearchTreeSize 283 - Quiescence search 284 - Evaluation (simple) 285 286 ### v0.4 (done) 287 - DONE 288 - Pondering 289 - Testing for correct play with Arena against Stockfish 290 - log files for standard and search log 291 - Implement simple Evaluator 292 - Complete simple search 293 - Implement simple Search 294 295 ### v0.3 (done) 296 - DONE: 297 - CleanUp and additional documentation 298 - complete uci options 299 - add log files to command line options 300 - make log files configurable 301 - make book configurable 302 - added uci options 303 - added configuration via file and command line 304 - search handling 305 - starting / stopping 306 - time control 307 - limits (except depth limit - needs simple search minimax) 308 309 ### v0.2 (done) 310 - DONE 311 - CleanUp 312 - Added logging 313 - TranspositionTable 314 - Perft enhanced and more tests 315 - UCI Handler enhanced 316 - Completed MoveGen 317 - OpeningBook base framework (reading and caching) 318 - Improve performance of Perft - otherwise not worth continuing 319 - Added MoveSlice - little optimization of MoveArray - usable directly as Slice 320 321 ### v0.1 (done) 322 - DONE: 323 - Perft works (1.353.761 nps / Java 3.5M, C++ 4.5M) - needs improvement 324 - MoveGenerator (all required for perft) 325 - Position (all required for perft) 326 - MoveArray and MoveList - both are for list of moves - MoveArray is faster for sorting 327 might be slower when inserting at the front - needs testing 328 - Most types (all required for perft) 329 330 ## Credits 331 - https://www.chessprogramming.org 332 - Stockfish / Tord Romstad, Marco Costalba, Joona Kiiski and Gary Linscott 333 - Crafty / Robert Hyatt 334 - TalkChess.org 335 - Flux, Pulse / Phokham Nonava 336 - Beowulf / Colin Frayn 337 - Mediocre / Jonatan Pettersson 338 - Bruce Moreland & GERBIL (http://www.brucemo.com/compchess/programming/index.htm) 339 - CPW-Engine / Pawel Koziol, Edmund Moshammer 340 - DarkThought / Ernst A. Heinz 341 - Arena Chess GUI / Martin Blume (Germany) et al 342 - and many more