algerbrex / blunder Goto Github PK
View Code? Open in Web Editor NEWA UCI compatible chess engine written in Golang
Home Page: https://algerbrex.github.io/
License: MIT License
A UCI compatible chess engine written in Golang
Home Page: https://algerbrex.github.io/
License: MIT License
I've been using your engine a bunch to compare the output to what mine is doing. In testing a particular endgame position, I noticed an the search was giving the same results after a ucinewgame command.
This position: 8/4k3/B7/4K2R/8/8/8/8 w - - 0 1
Run command "ucinewgame" followed by "position fen 8/4k3/B7/4K2R/8/8/8/8 w - - 0 1" then "go depth 12". At the end of the search, depth 12 has search 333340 nodes and found a mate-in-5. Then, repeat all the previous commands (ucinewgame, position, go). The output is now different: depth 12 has only searched 235775 nodes and only found a mate-in-7.
The outputs should be the same after a ucinewgame command.
fen: 8/8/2p5/3b1K1k/4p3/4PpR1/5P2/8 w - - 99 113
info depth 42 score cp 0 nodes 2378760 nps 2147718 time 1107 pv g3g7
info depth 43 score cp 0 nodes 1102889 nps 2175235 time 507 pv g3g7
info depth 44 score cp 0 nodes 1191410 nps 2155794 time 552 pv g3g7
info depth 45 score cp 0 nodes 214258 nps 2660628 time 80 pv g3g7
The position is mate in 1 (Rh3#) and not a draw, this happens because the mating move also allows draw by fifty move rule, however checkmate overwrites the fifty move rule.
The engine assumes that after the UCI "position ... moves" command is sent, there must be moves to parse. Since this isn't always the case, Blunder crashes on the following legal UCI input:
position fen r4rk1/pppnbppp/8/3P4/2PP2b1/P3KN2/1P2B1PP/RN5R w - - 1 1 moves
panic: runtime error: index out of range [252] with length 64
goroutine 1 [running]:
blunder/engine.MoveFromCoord(0xc000016136, {0xc000016136, 0x1})
C:/Users/deanm/Desktop/blunder/engine/move.go:100 +0x1db
blunder/engine.(*UCIInterface).positionCommandResponse(0xc0001e6000, {0xc0000160f0, 0x4c})
C:/Users/deanm/Desktop/blunder/engine/uci.go:84 +0x3ab
blunder/engine.(*UCIInterface).UCILoop(0xc0001e6000)
C:/Users/deanm/Desktop/blunder/engine/uci.go:262 +0x50f
blunder/engine.RunCommLoop()
C:/Users/deanm/Desktop/blunder/engine/comm.go:124 +0x6d4
main.main()
C:/Users/deanm/Desktop/blunder/blunder/main.go:6 +0x17
Thanks to Ed Schroder for helping to uncover this gem.
// Determine if it's legal for a pawn to double push,
// given it's color and origin square.
func canDoublePush(fromSq uint8, color uint8) bool {
if color == White {
return RankOf(fromSq) == Rank2
}
return RankOf(fromSq) == Rank6 // ---- should be Rank7 ----
}
…
if move.MoveType() == Castle {
if moved.Color == Black {
if (move.ToSq() == 62 && pos.CastlingRights&BlackKingsideRight == 0) ||
(move.ToSq() == 58 && pos.CastlingRights&BlackQueensideRight == 0) {
return false
}
} else {
if (move.ToSq() == 6 && pos.CastlingRights&BlackKingsideRight == 0) ||
(move.ToSq() == 2 && pos.CastlingRights&BlackQueensideRight == 0) {
return false
}
}
return true
}
…
i noticed Blunder can not do time-per-move in CuteChess !? This happens with v6.0.0 and v7.2.0 .. i tested both compiled versions and your assets .. is this UCI option not implemented ? When i set time-per-whole-game all is OK ..
I'm on Xubuntu 20.04 and CuteChess v1.2.0
THE BLUNDER-BUSS RAMPAGE
Intel i7 Quad
ChessGUI
256mb hash each
3-4-5 piece tablebases
Ponder off
ICOfy2013HQ.cgb book
40 moves in 16 minutes repeating (adapted for the CCRL)
2 cycles 30 rounds
All engines 64-bit 1CPU (where available)
Participants
KnightX 3.1 64-bit
Blunder 7.6.0 64-bit
Protej 0.6.1 64-bit
Chess Tiger 2007.1
ECE 20.1 64-bit
RookieMonster 0.9.4 64-bit
Fridolin 3.10 64-bit
Supernova 2.4 64-bit
Zevra 2.5 64-bit
Odonata 0.5.1 64-bit
Chessmaster 9000
Raven 1.20 64-bit
Myrddin 0.88 64-bit
Capivara LK 0.09b02g 64-bit
Jumbo 0.7.0 64-bit
Qapla 0.1.1 64-bit
Games and standings will be available after every six rounds from the following link:
http://kirill-kryukov.com/chess/discussion-board/viewtopic.php?f=7&t=13697
Web based link for live viewing (huge thanks to Jay - Berserk author).
http://tlcv.net/16093
Alternatively, if you install TLCV (Tom's Live Chess Viewer) on your computer, you can watch the games live move by move. You'll also be able to chat to others following the tournament in the chatroom there.
http://kirill-kryukov.com/chess/discussion-board/download/file.php?id=42959
Host - GrahamCCRL.dyndns.org Port - 16093
Linux users can use Livius:
https://github.com/kmar/livius
There is also a Livius windows version.
It has live pv boards as a nice addition.
http://www.crabaware.com/livius/
Hi, I noticed you are using the Fail-soft version of Alpha-beta algorithm.
In search.go there is this comment:
// Return the best score, which is alpha.
return bestScore
But I think that "bestScore" is not always alpha here, in Fail-soft Alpha-beta it can be lower than alpha (for so called "All-Nodes" where every move fails-low). Fail-soft is supposed to be optimization of alphabeta, in fail-soft version you don't clamp returned values to alpha/beta. But I noticed that you do clamp values returned from transposition table to alpha/beta in case of AlphaFlag/BetaFlag:
if entry.Flag == ExactFlag {
adjustedScore = score
}
if entry.Flag == AlphaFlag && score <= alpha {
adjustedScore = alpha
}
if entry.Flag == BetaFlag && score >= beta {
adjustedScore = beta
}
Shoudn't you just always do adjustedScore = score
? I checked source code of Stockfish and I think they don't clamp values returned from tt.
Another interesting topic is whether we should store "bestMove" for "All-Nodes" (AlphaFlag) or not. I noticed that you do store it, but Stockfish don't (they store "MOVE_NONE" in case of AlphaFlag).
For more details look here: https://stackoverflow.com/questions/72252975/transposition-table-look-up-for-fail-hard-vs-fail-soft-alpha-beta-how-do-they-d
I am new to this stuff so I may be wrong, but it's very interesting, what you think?
after i successfully compiled your v8.0.0 source code on Linux, i let the avx2 binary play a game against Prophet v4.2 (rating about 2400) .. Blunder lost that game due to a blunder in this position :
(i had to install GO v1.18 manually because my Xubuntu 21.10 has v1.17)
r1bq2k1/pp3rpp/2p2b2/3p4/1B6/1R1B3P/P1P2PP1/3QR1K1 b - - 0 20
after 35 seconds Blunder played 20...b6 ?? (at depth 16) which underestimates the danger 21.Qh5!
as soon as the game ended i let Blunder examine this position at higher depth .. indeed, then it finds 20...g6 is much better, but it takes a long time to discover this ..
here's the game .. the LiChess link shows a page with engine analysis by a modern StockFish version, which clearly indicates why 21.Qh5! is very strong .. but its line is not depth 16, so i wonder why Blunder doesn't see this continuation .. however, for a human player rated 1800+ this is obvious ?
[Event "engine vs engine"]
[Site "@ https://lichess.org/TCmrtIqc "]
[Date "2022.06.30"]
[White "Prophet v4.2"]
[Black "Blunder v8.0.0"]
[Result "1-0"]
[ECO "C67"]
[GameDuration "00:48:21"]
[Opening "Ruy Lopez"]
[PlyCount "133"]
[TimeControl "900+10"]
[Variation "Berlin defense, Open Variation"]
1. e4 {+0.20/14 38s} e5 {-0.23/19 28s} 2. Nf3 {+0.34/14 31s} Nc6 {-0.10/20 29s} 3. Bb5 {+0.30/14 28s} Nf6 {-0.30/17 30s} 4. O-O {+0.29/15 44s} Nxe4 {-0.09/19 31s} 5. d4 {+0.54/14 42s} exd4 {-0.16/20 41s} 6. Re1 {+0.50/14 32s} f5 {-0.16/21 33s} 7. Nbd2 {+0.55/14 40s} Be7 {-0.06/21 34s} 8. Nxe4 {+0.26/14 39s} fxe4 {-0.16/21 35s} 9. Rxe4 {+0.28/14 21s} O-O {-0.16/20 37s} 10. Nxd4 {+0.31/13 19s} Nxd4 {0.00/20 50s} 11. Qxd4 {+0.10/14 19s} d5 {+0.01/20 40s} 12. Re1 {-0.01/14 31s} Bf6 {+0.05/20 42s} 13. Qd1 {-0.02/14 36s} c6 {0.00/23 59s} 14. Bd3 {+0.16/15 22s} Qb6 {0.00/23 47s} 15. Be3 {+0.16/14 22s} Qxb2 {+0.03/24 64s} 16. Rb1 {+0.12/13 18s} Qc3 {0.00/24 58s} 17. Rb3 {+0.21/13 21s} Qa5 {+0.25/20 52s} 18. Bd2 {+0.33/12 33s} Qd8 {+0.34/19 49s} 19. Bb4 {0.00/12 32s} Rf7 {+0.51/17 42s} 20. h3 {-0.13/12 31s} b6 {+0.70/16 35s} 21. Qh5 {+1.18/12 26s} g6 {-1.70/25 35s} 22. Bxg6 {+2.24/18 30s} hxg6 {-1.78/25 30s} 23. Qxg6+ {+2.24/16 29s} Bg7 {-1.73/24 29s} 24. Rf3 {+2.03/14 28s} Bf5 {-1.84/24 27s} 25. Rxf5 {+2.03/15 16s} Rxf5 {-1.76/23 25s} 26. Qxf5 {+2.03/13 27s} Qf6 {-1.81/22 23s} 27. Qxf6 {+2.06/14 27s} Bxf6 {-1.43/23 22s} 28. Re6 {+1.87/17 19s} c5 {-1.36/23 21s} 29. Rxf6 {+1.91/16 21s} cxb4 {-1.36/21 20s} 30. Rc6 {+1.83/16 25s} a5 {-1.54/20 19s} 31. g3 {+1.79/15 24s} Re8 {-1.18/20 18s} 32. Kf1 {+1.76/16 23s} Re4 {-0.71/21 15s} 33. Rxb6 {+1.61/15 12s} a4 {-0.84/21 16s} 34. Rb5 {+1.40/15 21s} Rc4 {-1.07/25 20s} 35. Rxd5 {+1.73/17 23s} Rxc2 {-1.42/24 15s} 36. Rb5 {+1.73/15 22s} b3 {-1.38/18 12s} 37. axb3 {+3.31/20 13s} a3 {-2.79/26 12s} 38. Ra5 {+3.36/19 22s} a2 {-2.97/25 11s} 39. Kg2 {+3.46/18 21s} Kf7 {-3.22/24 11s} 40. Ra7+ {+3.37/17 21s} Ke6 {-3.03/25 11s} 41. h4 {+3.52/17 17s} Kd5 {-3.16/24 11s} 42. h5 {+3.35/16 12s} Kc6 {-3.60/22 11s} 43. h6 {+3.56/16 10s} Kb6 {-3.88/28 14s} 44. h7 {+3.40/17 12s} Rc8 {-4.25/28 17s} 45. Rxa2 {+3.40/15 20s} Rh8 {-4.26/24 9.4s} 46. f4 {+3.69/17 11s} Rxh7 {-5.59/27 9.4s} 47. f5 {+3.72/16 19s} Kc6 {-5.59/25 9.5s} 48. g4 {+3.70/16 19s} Rg7 {-4.10/21 13s} 49. Ra4 {+3.77/16 19s} Rb7 {-4.38/22 12s} 50. f6 {+3.83/15 18s} Kd7 {-4.87/21 9.0s} 51. Rf4 {+3.87/16 18s} Ke8 {-6.15/26 9.2s} 52. b4 {+4.45/18 18s} Kf7 {-5.85/29 9.1s} 53. g5 {+5.23/19 9.9s} Rb8 {-5.85/27 9.2s} 54. Kf3 {+5.23/17 17s} Rb7 {-6.03/24 9.3s} 55. Kg3 {+6.74/17 9.9s} Rb8 {-9.73/23 9.4s} 56. b5 {+7.31/19 14s} Rxb5 {-5.36/29 9.5s} 57. g6+ {+7.31/17 17s} Kxg6 {-6.10/28 10s} 58. f7 {+7.55/20 8.8s} Rg5+ {-M20/21 9.5s} 59. Kf3 {+12.65/13 17s} Rf5 {-M16/22 9.6s} 60. Rxf5 {+13.00/14 17s} Kxf5 {-M14/24 9.6s} 61. f8=Q+ {+13.05/13 16s} Ke6 {-M12/22 9.8s} 62. Ke4 {+327.56/12 16s} Kd7 {-M10/25 13s} 63. Kd5 {+327.58/10 16s} Kc7 {-M8/26 12s} 64. Qa8 {+327.60/8 0.14s} Kd7 {-M6/25 9.1s} 65. Qb7+ {+327.62/5 0.008s} Ke8 {-M4/26 12s} 66. Ke6 {+327.64/3 0.001s} Kd8 {-M2/28 12s} 67. Qd7# {+327.66/1 0s, White mates} 1-0
Can you build a Korean chess engine?
engine/search.go
func (search *Search) Search() Move {
…
if score <= alpha || score >= beta {
alpha = -Inf
beta = Inf
depth--
// important check -----------------------------------------------
if depth == 0 {
break
}
// important check -----------------------------------------------
continue
}
…
}
Start server, send command "go", the application crashes.
> go
panic: runtime error: index out of range [64] with length 64
goroutine 49 [running]:
blunder/engine.genBishopMoves(...)
.../go/src/github.com/algerbrex/blunder/engine/movegen.go:100
blunder/engine.sqIsAttacked(0x0, 0x0, 0x0)
.../go/src/github.com/algerbrex/blunder/engine/movegen.go:235 +0x1fe
blunder/engine.(*Position).InCheck(0x0)
.../go/src/github.com/algerbrex/blunder/engine/board.go:599 +0x4f
blunder/engine.(*Search).negamax(0xc000190000, 0x1, 0x0, 0xd8f0, 0x2710, 0xc0000bde50, 0x1)
.../go/src/github.com/algerbrex/blunder/engine/search.go:188 +0xf0
blunder/engine.(*Search).Search(0xc000190000)
.../go/src/github.com/algerbrex/blunder/engine/search.go:111 +0x2d5
blunder/engine.goCommandResponse(0xc000190000, {0xc0000b2010, 0x3})
.../go/src/github.com/algerbrex/blunder/engine/uci.go:147 +0x157
created by blunder/engine.UCILoop
.../go/src/github.com/algerbrex/blunder/engine/uci.go:187 +0x5dd
exit status 2
While with a well behaved client this shouldn't happen it would be good if the application was more resilient to crashes.
I have been trying the latest version, using the binaries (both default and popcnt) that come with the release on an Apple M1. Below is the screen capture:
MacBook-Pro macOS % ./blunder-8.5.5-default
Finding rook and bishop magics...
Done finding rook and bishop magics.
██████╗░██╗░░░░░██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░
██╔══██╗██║░░░░░██║░░░██║████╗░██║██╔══██╗██╔════╝██╔══██╗
██████╦╝██║░░░░░██║░░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝
██╔══██╗██║░░░░░██║░░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗
██████╦╝███████╗╚██████╔╝██║░╚███║██████╔╝███████╗██║░░██║
╚═════╝░╚══════╝░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝
Author: Christian Dean
Engine: Blunder 8.5.5
Email: [email protected]
Hash size: 64 MB
Perft hash size: 64 MB
Commands:
- uci: Start the UCI protocol
- tt <SIZE>: Set the size of the transposition table used with perft to be <SIZE> MB
- perft <DEPTH>: Run perft up to <DEPTH>
- dperft <DEPTH>: Run divide perft up to <DEPTH>
- fen <FEN>: Load a fen string given by <FEN>
- print: Display the current board state
- eval: Display the static evaluation of the current position
- help: Display this help message
- quit: Quit the program
uci
id name Blunder 8.5.5
id author Christian Dean
option name Hash type spin default 64 min 1 max 32000
option name Clear Hash type button
option name Clear History type button
option name Clear Killers type button
option name Clear Counters type button
option name UseBook type check default false
option name BookPath type string default
option name BookMoveDelay type spin default 2 min 0 max 10
Available UCI commands:
* uci
* isready
* ucinewgame
* setoption name <NAME> value <VALUE>
* position
* fen <FEN>
* startpos
* go
* wtime <MILLISECONDS>
* btime <MILLISECONDS>
* winc <MILLISECONDS>
* binc <MILLISECONDS>
* movestogo <INTEGER>
* depth <INTEGER>
* nodes <INTEGER>
* movetime <MILLISECONDS>
* infinite
* stop
* quit
uciok
isready
readyok
ucinewgame
position fen r1bqk1r1/1p1p1n2/p1n2pN1/2p1b2Q/2P1Pp2/1PN5/PB4PP/R4RK1 w q -
panic: runtime error: slice bounds out of range [:6] with capacity 4
goroutine 1 [running]:
blunder/engine.(*UCIInterface).positionCommandResponse(0xc000260000, {0xc00001c140?, 0x4b?})
C:/Users/deanm/Desktop/blunder/engine/uci.go:73 +0x4c6
blunder/engine.(*UCIInterface).UCILoop(0xc000260000)
C:/Users/deanm/Desktop/blunder/engine/uci.go:250 +0x539
blunder/engine.RunCommLoop()
C:/Users/deanm/Desktop/blunder/engine/comm.go:148 +0x832
main.main()
C:/Users/deanm/Desktop/blunder/blunder/main.go:16 +0x17
Lately i stumbled upon this typical position :
White to move.
it's a position from one of the well known 15 test suites at https://sites.google.com/site/strategictestsuite/about-1 .. this is an old site and some links are broken, but here you can find all these 15 EPD files for download. In one of them was this EPD :
rk6/pP1p2p1/B7/3K1P2/8/8/7b/8 w - - bm f6;
yes, the move (here comes the spoiler) f6 is best !
the reason is simple : Black must take the pawn, so the White King can walk on the white squares and reach the backrow on the d file and after b7xa8 Kxa8 he can even come to c8 and give mate by the Bishop. The black squared Black Bishop can do nothing about this King walk, but most engines do not see this : their search may reach deep but the almost forced solution line seems over their horizon .. only one strong engine finds it : ShashChess, a special Stockfish version, based on the theory of Alexander Shashin, see https://github.com/amchess/ShashChess/ i used a python script which i'm developing since one month. Take a close look at this screencast - the displayed information of the data flow should tell a lot about how engines calculate :
9 engines should find f6 !
https://www.bitchute.com/video/u8weJhqR05gw/
and here's a short one with two Blunders :
hope you like the music !
i can elaborate about this position and the data flow you see in the screencasts.
so, the question is : why do most engines have no clue in this position or alike ?
Recently i was testing the following position on several engines. It's from the game Giri vs. Firouzja at the Tata Steel Masters tournament 2021, eg. see https://chess24.com/en/watch/live-tournaments/tata-steel-masters-2021/12/1/4
After 60...Nf4 this position was on the board :
r7/P5R1/2k5/8/1P3n1P/K7/6P1/8 w - - 0 18
White to play. The only winning move is Ka4. Not many engines find this. Using multipv 1, Blunder finds this move as best after 2 minutes (i'm using Xubuntu 20.04 on a modern notebook). This position and its "solution" are interesting, but i open this Issue because Blunder seems to output a faulty time, see the yellow-red marker dot i put in the image - i used SCID v4.7.1 for this.
Normally these times in SCID are increasing, they represent the total time. But it looks like Blunder outputs how much time the evaluation took for each depth, not the total time !?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.