{"id":46670337,"url":"https://github.com/dimdano/numbfish","last_synced_at":"2026-03-08T21:51:45.236Z","repository":{"id":222273892,"uuid":"573165648","full_name":"dimdano/numbfish","owner":"dimdano","description":"♟︎ A strong python chess bot running on 1-thread","archived":false,"fork":false,"pushed_at":"2023-03-07T11:31:53.000Z","size":15713,"stargazers_count":36,"open_issues_count":5,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-16T04:16:28.169Z","etag":null,"topics":["ai","chess","chess-engine","lichess","nnue","numbfish","numpy","python","stockfish","sunfish"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dimdano.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-12-01T20:59:30.000Z","updated_at":"2025-11-08T12:46:53.000Z","dependencies_parsed_at":"2024-02-13T10:48:20.720Z","dependency_job_id":null,"html_url":"https://github.com/dimdano/numbfish","commit_stats":null,"previous_names":["dimdano/numbfish"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dimdano/numbfish","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdano%2Fnumbfish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdano%2Fnumbfish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdano%2Fnumbfish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdano%2Fnumbfish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimdano","download_url":"https://codeload.github.com/dimdano/numbfish/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdano%2Fnumbfish/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30274852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","chess","chess-engine","lichess","nnue","numbfish","numpy","python","stockfish","sunfish"],"created_at":"2026-03-08T21:51:44.661Z","updated_at":"2026-03-08T21:51:45.228Z","avatar_url":"https://github.com/dimdano.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://github.com/dimdano/numbfish/blob/main/logo/numbfish_logo.jpg\" width=60% height=60%\u003e\n\n## Introduction\nNumbfish is a simple but strong pythonic chess engine. Numbfish is based on Sunfish but with several additional features, the most important of which is an Efficiently Updatable Neural Network (NNUE) implemented and optimized first time using numpy. \nNNUE is *efficiently* implemented using incremental updates of the input layer outputs in make and unmake moves just like Stockfish does in C++. The additional positional information entailed from NNUE makes this engine *probably* **the strongest python engine** running on 1-thread CPU.\n\n\n## About Numbfish\n Numbfish keeps a very simple but optimized python interface, taking up just 140 lines of code! (see [`compressed.py`](https://github.com/dimdano/numbfish/blob/master/compressed.py)) \u003cbr /\u003e Yet it plays at 2300 ratings at Lichess. You can challenge [numbfish_bot](https://lichess.org/@/numbfish_bot) for 5+0 min games!\n\nBecause Numbfish is small and strives to be simple, the code provides a great platform for experimenting. My NNUE implementation is a bit complex to understand and a more explanatory guide is needed of how I made it work in python. However people can fork my project and experiment with other features as well.  Make sure to drop a :star:. If you make Numbfish stronger I will merge your improvements!\n\n\n## Run it!\n\nThis project needs python \u003e= 3.7. Also install the required packages with `pip install -r requirements.txt` \u003cbr /\u003e\nNumbfish is optimized for 5+0 min games through `uci.py`. It communicates through UCI protocol by the command `python3 -u uci.py`. You can also play it through the chess GUI of you choice such as [cutechess](https://cutechess.com/).\n\nIf you want to just test it with UCI commands through terminal set PLAY_5min flag to False in `uci.py`.\n\nLast, if you want to casually play from terminal run `python3 play_terminal.py` instead. \u003cbr /\u003e\n*(just make sure to set OPENING_BOOK to False in `numbfish.py`)*\n\n#### Interface from terminal play\n\u003cimg src=\"https://github.com/dimdano/numbfish/blob/main/logo/terminal_play.png\" width=40% height=40%\u003e\n\n## Features\n\n1. Built around the simple, but deadly efficient MTD-bi search algorithm.\n2. Filled with classic as well as modern 'chess engine tricks' for simpler and faster code.\n3. Evaluation is based on smart NNUE inference as well as classic Piece Square Tables evaluation for end games.\n4. Uses standard Python collections and data structures for clarity and efficiency.\n\n## About NNUE implementation in python\n\n\u003cimg src=\"https://github.com/dimdano/numbfish/blob/main/logo/HalfKP.png\" width=70% height=70%\u003e\n\nNumbfish has a very efficient implementation of NNUE written with numpy operations along with neural network inference using [tf-lite](https://www.tensorflow.org/lite/). \u003cbr /\u003e \n- First, the model of HalfKP structure was implemented in Tensorflow and the weights and biases of trained NNUE were loaded. Then the first half of the model up to the 2x256 layer output was implemented using fast numpy operations. The accumulator has a \"white king\" half and a \"black king\" half, where each half is a 256-element vector, which is equal to the sum of the weights of the \"active\" features plus the biases. The active features are gathered fast from the transformer weights using the indices of the pieces as the operations are sparse. Also an accum_update function was implemented to do incremental updates of the accumulator on new moves, changing only the indices of the changed pieces when needed. Although int16 operations can be used, no perfomance increase was observed so I left float32 datatypes. \u003cbr /\u003e \n- The second part of the model which begins with a clipped ReLU function and 2x256 input, and ends with the final evaluation was implemented using tf-lite for very low latency. Here float16 datatype for tflite model was used. \u003cbr /\u003e \u003cbr /\u003e \n\n**Weights and biases are taken from* [nn-62ef826d1a6d.nnue](https://tests.stockfishchess.org/nns?network_name=nn-62ef826d1a6d.nnue\u0026user=\u0026master_only=on)\n\n\n## Performance and Limitations \n\nNumbfish supports castling, en passant, and promotion. It doesn't however do minor promotions to rooks, knights or bishops.\nAlso, the NNUE inference (specifically the accumulator update) does not take into account the en passant cases. Left for future work.\nLast, in chess matches the engine adds previous positions in history to avoid 3-fold repetitions. Although with this implementation it avoids 2-fold repetitions which might not be good.\n\nNumbfish is strong when it runs on a fast CPU core especially when reaching \u003e5 depths in games. Below are the results from 5+0 min games of Numbfish vs Sunfish running both on a i7-8700 CPU. \u003cbr /\u003e \nIt's worth mentioning that Numbfish achieves ~14K NPS, almost 1/4 of the NPS of Sunfish (~54K NPS), however it wins in most of the matches. Below are some winning percentages after several tests I did but more games are needed to have a final conclusion.\n\n    Name                          Games   Wins   Draws\n    Numbfish vs Sunfish           30      90%     7%\n\n\n\n## How to make Numbfish stronger\n\n- add dedicated capture generation or check detection\n- add the en passant case for the accumulator update function in order to avoid blunders\n- move everything to bitboards using chess library\n- implement a more recent NNUE structure such as HalfKAv2\n- implement parallel search\n\n## Why Numbfish?\n\nThe name Numbfish actually refers to the [numbfish](https://en.wikipedia.org/wiki/Narcinidae), which has numb as first name and more or less refers to numpy. Although numba is a more similar word, I sinfully :smiling_imp: left the numba implementation as a future work (should give minor improvements though).\nThe use of a fish at the end is in the spirit of the great open source chess engines such as Stockfish!\n\n\n## Credit\n\n[Sunfish](https://github.com/thomasahle/sunfish)\n\n[Stockfish](https://github.com/official-stockfish/Stockfish) \n\n[Stockfish NNUE](https://www.chessprogramming.org/Stockfish_NNUE)\n\n[Chess Opening Books](https://sites.google.com/site/computerschess/download?pli=1)\n\n*Feel free to contact me if you have any questions*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimdano%2Fnumbfish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimdano%2Fnumbfish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimdano%2Fnumbfish/lists"}