badkins
2021-2-5 16:37:59

Yes, I did racket -l errortrace -t chess.rkt and got some more granular output. Even w/o errortrace, I think profile will get me there.


badkins
2021-2-5 16:40:24

Once I found <https://docs.racket-lang.org/profile/index.html?q=profiler#%28def._%28%28lib._profile%2Fanalyzer..rkt%29._profile%29%29|Section 4.1> , the output became so clear!


badkins
2021-2-5 16:46:14

Yeah, that is interesting.


yilin.wei10
2021-2-5 17:29:58

Am I right in thinking that typed racket doesn’t support kw-args in it’s dependent function types? https://docs.racket-lang.org/ts-reference/Experimental_Features.html


anything
2021-2-5 20:03:35

That is so interesting. I might actually improve a thing or two now. Thanks!


badkins
2021-2-5 20:32:27

My engine is getting better. It recently beat a 1,900 human player, but I think that was a fluke. I can still beat it if I concentrate. Here’s today’s game where I beat it :) 1. d4 d5 2. Nf3 Nc6 3. e3 Be6 4. Bd3 Qd7 5. a3 O-O-O 6. Nbd2 Nh6 7. h3 Re8 8. b3 f6 9. Bb2 Rd8 10. Qe2 Qe8 11. O-O-O Bf7 12. g4 e5 13. Bb5 exd4 14. Bxc6 Qxc6 15. Nxd4 Qb6 16. Qb5 Qxb5 17. Nxb5 a6 18. Nd4 Re8 19. Rhe1 Bg6 20. f4 c5 21. N4f3 Be7 22. f5 Bf7 23. c4 dxc4 24. bxc4 Bd6 25. Kc2 Ref8 26. Kc3 Be5+ 27. Nxe5 fxe5 28. Ne4 Rd8 29. Nxc5 Rxd1 30. Rxd1 Re8 31. e4 Re7 32. a4 Rc7 33. Ne6 Bxe6 34. fxe6 b5 35. axb5 axb5 36. c5 Rxc5+ 37. Kb4 Rc7 38. Rd5 Re7 39. Rxe5 Kd8 40. Rd5+ Ke8 41. Rd6 Rc7 42. Kxb5 Ke7 43. Ba3 Ke8 44. Ra6 Rc8 45. Ra7 Rd8 46. Rxg7 Rb8+ 47. Kc6 Rc8+ 48. Kd5 Ra8 49. Bc5 Rd8+ 50. Ke5 Rd3 51. Rxh7 Kd8 52. Rxh6 Kc8 53. Rh7 Rd8 54. g5 Kb8 55. g6 Rg8 56. Kf6 Kc8 57. g7 Kc7 58. Rh8 Rxg7 59. Kxg7 Kc6 60. e7 Kxc5 61. e8=Q Kd4 62. Qc6 Ke3 63. Rf8 Kd3 64. Rf3+ Kd2 65. Qc3+ Ke2 66. Qd3+ Ke1 67. Rf1# Engine was playing black, and Stockfish says it blundered with move 26. It currently has very few features, just simple alpha-beta, very simple evaluation function and simple move ordering (most valuable victim, least valuable attacker i.e. MVV-LVA). I’ll be adding a transposition table & better evaluation next.


badkins
2021-2-5 20:35:27

I implemented “perft” to check the move generation and legality checks. It does about 3.9M nodes per second compared to 50M to 100M or more for engines in C++ or Rust. With some tuning, I may be able to get it up to 5M, or so which should be enough for my purposes.


badkins
2021-2-5 20:36:07

Search is only 500K to 1M nodes per second at the moment, but with the alpha-beta and move ordering, it can go pretty deep sometimes.


soegaard2
2021-2-5 20:36:27
  1. … Nh6 is a bit odd

badkins
2021-2-5 20:38:05

I don’t have a piece square table yet (which reminds me, that’s before transposition & evaluation!), so my dumb evaluation can make for some interesting moves. In this case, I have a small bonus for just moving the knights & bishops initially - it didn’t care where it moves, as long as there’s no material loss.


soegaard2
2021-2-5 20:41:59

Interesting game. https://lichess.org/study/XvYUgXin The first mistake according to Stockfish is 26. … Be5+ . I think, Stockfish is unhappy about giving up the bishop pair for nothing. But that’s hard for a simple engine.


soegaard2
2021-2-5 20:43:14

The poor knight stays on h6 until it is taken :slightly_smiling_face:


badkins
2021-2-5 20:44:04

I just pushed the <https://github.com/lojic/RacketChess/tree/development|development branch> if you want to try it out. rlwrap racket chess.rkt then enter w or b to tell the computer to play as white or black. When you enter a move, you can also add a think time :) For example: d5 30 will move the pawn to d5 and set the think time to 30 seconds. It will stay at 30 seconds per move until changed.


soegaard2
2021-2-5 20:44:18

How does it work with piece square tables? Different values for each piece and move number?


badkins
2021-2-5 20:45:28

As I understand it, a piece square table has a value for each square on the board for each piece, so an array for each piece. The value of the piece ends up being the normal value plus whatever is in that square. This will encourage certain behaviors such as getting the king active in the middle during the end game, etc.


badkins
2021-2-5 20:46:09

I think there is usually one set of tables for opening/middle & another set for end game. That’s enough to find mate in the endgame without having to have an endgame table.


soegaard2
2021-2-5 20:46:31

Sounds pretty simple - but deriving the numbers…


badkins
2021-2-5 20:46:36

It will needlessly get into stalemate now, and sometimes it will perpetually check.


badkins
2021-2-5 20:47:07

Yes, some people do supervised/reinforcment learning for the numbers, but I think in my case, I’ll start with a generic set of tables from another engine before getting fancy.


soegaard2
2021-2-5 20:47:29

Makes sense.


badkins
2021-2-5 20:48:24

I give <https://github.com/lojic/RacketChess/blob/8a2f6b5f0bde74ca463c43ee7e4a6fe81be66742/src/evaluation.rkt#L37|a bonus> for the king being on a castled square, but since I don’t deal with the rook, I saw the engine move the king to the castled square in two steps for one game while leaving the rook in the original spot which trapped the rook :)


badkins
2021-2-5 20:48:48

I just hacked up a few ideas in that evaluate function so I could try it out.


badkins
2021-2-5 20:49:35

So far, the biggest change was adding quiescent search - that was huge re: making it stronger!


badkins
2021-2-5 20:50:16

When I get far enough, I’m going to start a series of blog posts that will create a Racket chess engine bit by bit, I’m really looking forward to that!


soegaard2
2021-2-5 20:50:52

What’s “quiescent search”?

I’ll definitely look forward to a blog series!


soegaard2
2021-2-5 20:54:02

I am confused about the entering the time:


yilin.wei10
2021-2-5 20:59:30

OK looking at the actual, I don’t think it does


yilin.wei10
2021-2-5 20:59:37

*file


badkins
2021-2-5 21:08:45

Hmm.. let me try…


badkins
2021-2-5 21:09:23

I think you entered too soon - wait for the “Enter move:” prompt


badkins
2021-2-5 21:10:28

Shoot - I think I broke something when hurriedly pushing the last commit. Hold on…


soegaard2
2021-2-5 21:10:52

I see that prompt, but it disappears after entering d4 30


soegaard2
2021-2-5 21:11:43

Wait. I am using 7.5. I should probably use a newer Racket. What are you on?


badkins
2021-2-5 21:16:34

Ok, I pushed a fix, it’s playing again. The code in chess.rkt and the top level search function are hacky at the moment. I’m running Racket v7.9 [cs]


badkins
2021-2-5 21:17:31

badkins@create src % rlwrap racket chess.rkt Computer plays white or black? (w or b): b Enter move: d4 30 --------------------------------- \| r \| n \| b \| q \| k \| b \| n \| r \| 8 --------------------------------- \| p \| p \| p \| p \| p \| p \| p \| p \| 7 --------------------------------- \| \| \| \| \| \| \| \| \| 6 --------------------------------- \| \| \| \| \| \| \| \| \| 5 --------------------------------- \| \| \| \| P \| \| \| \| \| 4 --------------------------------- \| \| \| \| \| \| \| \| \| 3 --------------------------------- \| P \| P \| P \| \| P \| P \| P \| P \| 2 --------------------------------- \| R \| N \| B \| Q \| K \| B \| N \| R \| 1 --------------------------------- \| a \| b \| c \| d \| e \| f \| g \| h \| Black's move Depth: 1. Move-i: 1. EP Square: d3. White king pos: e1, Black king pos: e8 Castling: KQkq Best move (1): pd7-d5 Best move (2): pd7-d5 Best move (3): pd7-d5 Best move (4): pd7-d5 Best move (5): pd7-d5 Best move (6): pd7-d5 570026.6666666666 nodes per second --------------------------------- \| r \| n \| b \| q \| k \| b \| n \| r \| 8 --------------------------------- \| p \| p \| p \| \| p \| p \| p \| p \| 7 --------------------------------- \| \| \| \| \| \| \| \| \| 6 --------------------------------- \| \| \| \| p \| \| \| \| \| 5 --------------------------------- \| \| \| \| P \| \| \| \| \| 4 --------------------------------- \| \| \| \| \| \| \| \| \| 3 --------------------------------- \| P \| P \| P \| \| P \| P \| P \| P \| 2 --------------------------------- \| R \| N \| B \| Q \| K \| B \| N \| R \| 1 --------------------------------- \| a \| b \| c \| d \| e \| f \| g \| h \| White's move Depth: 1. Move-i: 2. EP Square: d6. White king pos: e1, Black king pos: e8 Castling: KQkq pd7-d5 Score: 0.01 Enter move:


badkins
2021-2-5 21:18:27

I think it should work just fine on 7.5


badkins
2021-2-5 21:18:34

I’m running MacOS


badkins
2021-2-5 21:22:56

@soegaard2 quiescent search works like this - you do an alpha-beta search to a given depth i.e. 3, then, instead of simply returning the evaluation of the board, you enter a quiescent search which only searches capture moves until there are no more, then it returns a static evaluation of the board. That is to prevent you taking a pawn with your Queen, and thinking everything is ok :) It plays out all the captures & recaptures until the board is “quiet” before giving an evaluation. It’s important to have some reasonable move ordering in place first otherwise queens would just go on a rampage gobbling up pawns and the search would combinatorially explode. By having decent move ordering, the alpha beta will prune very well, and it will “quiesce” quickly enough.


badkins
2021-2-5 21:24:19

I really need to get to the point where I can “plug in” my engine to an app along with another engine and let them play a bunch of games. This way I can make a change, and see if it beats the older version.


badkins
2021-2-5 21:25:17

Stockfish is amazing - I made it sacrifice its queen, and it still beat my engine !!!


soegaard2
2021-2-5 21:27:21

Ah! Figured it out. I thought, I were on the development branch, but I wasn’t. Now it works.


soegaard2
2021-2-5 21:28:36

Thanks for the explanation of quiescent search.


badkins
2021-2-5 21:31:36

Hmm.. that’s even worse if the main branch was failing! I’ll probably merge dev into master soon.


badkins
2021-2-5 21:32:59

Once I get the UCI stuff coded, you can plug in the engine to a GUI - that’s probably the way to go vs. developing the GUI part.


soegaard2
2021-2-5 21:34:35

It’s playing well so far.


badkins
2021-2-5 21:34:42

To play the engine now, I start my Stockfish app which has a nice board where you can move the pieces, the console display of the board is not good :)


badkins
2021-2-5 21:35:10

If you give it 30s per move, it’s pretty tough depending on your skill level.


soegaard2
2021-2-5 21:35:13

soegaard2
2021-2-5 21:39:09

Is the score measured in pawns?


badkins
2021-2-5 21:40:10

Basically. I use centipawns where a pawn = 100 centipawns, but when I display the score in the console, I divide by 100, so it’s back to pawns.


soegaard2
2021-2-5 21:45:52

How do you enter castles? Ke1-g1 is in the list of generated moves, but I get: Move not in generated list Ke1-g1 pgn-move: no pattern found for move


badkins
2021-2-5 21:51:27

O-O or O-O-O


soegaard2
2021-2-5 21:52:02

Of course. I tried o-o, but I guess that’s for black.


badkins
2021-2-5 21:52:16

O-O for kingside, O-O-O for queenside - maybe it needs capital O’s ?


badkins
2021-2-5 21:52:33

I don’t remember if I upcase it or not


badkins
2021-2-5 21:54:32

@soegaard2 can you give me the lichess link to watch? :)


soegaard2
2021-2-5 21:54:50

badkins
2021-2-5 21:57:34

are you white or black?


soegaard2
2021-2-5 21:57:52

I am white. I already lost a pawn :disappointed:


badkins
2021-2-5 22:02:09

It knows nothing about king safety :)


badkins
2021-2-5 22:02:24

You have a nice pawn shield for your king.


badkins
2021-2-5 22:04:26

I’m no expert, but you have all your pieces in play, and one black rook is useless now.


soegaard2
2021-2-5 22:05:45

Yes - I am however mostly playing bullet, and bullet tricks doesn’t work here.


badkins
2021-2-5 22:07:24

Yes. The engine isn’t too smart, but it’s reasonably tactical - it shouldn’t make any obvious blunders like losing a piece unless it’s just outplayed positionally.


badkins
2021-2-5 22:08:22

lol - you must be doing well when it just moves its rook back like that! :)


soegaard2
2021-2-5 22:08:39

Yeah, that were an odd move.


badkins
2021-2-5 22:08:52

Whenever I see an engine waste a move, I get encouraged :)


badkins
2021-2-5 22:12:03

That was fast - are you giving it less think time? :)


soegaard2
2021-2-5 22:12:17

Still 30


soegaard2
2021-2-5 22:13:44

Somehow I need replace my knight.


badkins
2021-2-5 22:15:36

Hmm.. that move was 16 seconds. I think you changed the think time - maybe accidentally.


badkins
2021-2-5 22:15:55

It should still play ok though.


badkins
2021-2-5 22:16:09

Or maybe lichess has lags


soegaard2
2021-2-5 22:16:13

It plays fine. A but passive, but no mistakes.


badkins
2021-2-5 22:18:26

weird, I expected it to move Nd6


soegaard2
2021-2-5 22:18:35

Ditto


badkins
2021-2-5 22:19:38

surely it won’t allow the fork :)


badkins
2021-2-5 22:21:04

I’m more interested in this game, than in watching the world champion play :)


soegaard2
2021-2-5 22:22:05

More rook moves.


badkins
2021-2-5 22:23:26

Its end game is weak, so if you can survive long enough, you should be able to outplay it in the endgame.


soegaard2
2021-2-5 22:23:54

The score now says 999.8, so there must be something here …


badkins
2021-2-5 22:24:14

oh, you have mate then!


soegaard2
2021-2-5 22:24:39

Wrong move. Score dropped to 9.


soegaard2
2021-2-5 22:29:01

Okay. No reason to play further. You are spot on about surviving the opening/middle game.


soegaard2
2021-2-5 22:29:58

Calculating a move or two further might have saved the situation in this game.


badkins
2021-2-5 22:30:55

Good job :)


soegaard2
2021-2-5 22:31:09

I botched the opening though.


soegaard2
2021-2-5 22:32:19

I think, it was a good decision to get the queens of the board.


soegaard2
2021-2-5 22:32:27

(from my perspective)


badkins
2021-2-5 22:33:10

I agree. I always try and simplify since it’s so good at looking 3 to 5 moves ahead :)


badkins
2021-2-5 22:33:50

It has no opening intelligence. I simply gave a small bonus to 1) pawns on a center square, and 2) knights/bishops that have been moved, and that seems to make it play a “reasonable” opening.


badkins
2021-2-5 22:34:16

Adding some good piece square tables will make it pretty formidable I think.


soegaard2
2021-2-5 22:34:20

Yeah - that’s why I am annoyed it played better than me in the opening :slightly_smiling_face:


soegaard2
2021-2-5 22:34:40

Have you seen Hikarus game against the engine Rybka?



soegaard2
2021-2-5 22:35:54

The problem for the engine is again the long term strategy.


badkins
2021-2-5 22:35:58

No, I’ll check it out. Thanks for trying out the engine by the way, that was fun :) I’ll make more progess over the weekend.


soegaard2
2021-2-5 22:36:21

It’s a cool project. I am impressed by how well it plays already.


badkins
2021-2-5 22:37:19

Me too actually :) I’ll walk through that Hikaru vs. Rybka game w/ Stockfish and see how often Stockfish suggests the move.


soegaard2
2021-2-5 22:38:18

Hmm. Hadn’t thought about it. Someone much have entered the pgn somewhere.



badkins
2021-2-5 22:54:34

lol all those bishop & knight promotions!


badkins
2021-2-5 22:55:53

Wow, that was 3 minute no increment ?!?!


soegaard2
2021-2-5 22:56:30

Oh!


soegaard2
2021-2-5 22:58:11

Hikaru is scary fast. I watched him solve puzzles. He plays the solution faster, than I can see, where all the pieces.


soegaard2
2021-2-5 22:58:12

are


badkins
2021-2-5 22:58:57

I would love to see that in real time.



badkins
2021-2-6 02:53:50

@soegaard2 I added the piece square tables (PST) functionality. Accidentally pushed to master, but it seems to be working well. Much better than my goofy evaluation heuristics :)


badkins
2021-2-6 02:54:52

I didn’t have time to properly determine when “end game” starts, so it just switches from middle to end game after 50 ply. Close enough for now.


badkins
2021-2-6 02:55:30

The only piece that changes is the King - end game table encourages moving it to the center. Middle game encourages castling and staying behind the pawn shield.


badkins
2021-2-6 02:56:28

I just followed this pretty much verbatim: https://www.chessprogramming.org/Simplified_Evaluation_Function but I made an important change to the Rook table to encourage castling after it failed to do so with the original Rook table.