GithubHelp home page GithubHelp logo

algerbrex / blunder Goto Github PK

View Code? Open in Web Editor NEW
234.0 7.0 15.0 2.06 MB

A UCI compatible chess engine written in Golang

Home Page: https://algerbrex.github.io/

License: MIT License

Go 99.02% Makefile 0.82% Python 0.16%
golang go chess

blunder's People

Contributors

algerbrex avatar antham avatar bernhard-hofmann avatar mvanthoor avatar shteou avatar splch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

blunder's Issues

Different search results on the same position after a ucinewgame command

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.

Draw score because of fifty move rule when it's mate

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.

Engine crashes when sent the UCI "position ... moves" command without any moves.

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.

Error checking for a pawn to double push (canDoublePush)

// 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 ----
}

Perhaps a check for castling is needed in MoveIsPseduoLegal?

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
}
…

UCI option Time-Per-Move ?

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

New Tournament with Blunder included

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/

Fail-soft search but Fail-hard transposition table look up?

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?

Blunder v8.0.0 underestimates danger ?

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

blunder_b6

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

it is necessary to put a check in Search() for boundary values

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
    }
…
}

Application crashes if trying to run when board is not initialized

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.

Crashed with Apple silicon M1

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

just win on the white squares

Lately i stumbled upon this typical position :

diagram_f6

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 :

film2_two_blunders_converted.mp4

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 ?

faulty duration time in SCID

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 :

blunder_v7 6 0_strange_time

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 !?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.