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