Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unclear Turo ply count while mate #2

Closed
tissatussa opened this issue Aug 12, 2023 · 17 comments
Closed

unclear Turo ply count while mate #2

tissatussa opened this issue Aug 12, 2023 · 17 comments

Comments

@tissatussa
Copy link

hi,

using your Morlock Turo version, i just encountered a strange move by the engine, considering i set ply 6 in this game :

morlock-turo-ply6-dia1

here White (Turo ply 6) played Nf3xg5! which is a good move, making the white squares free for the Queen to give check and attack the opponent King .. Black took the kNight and we have this position :

morlock-turo-ply6-dia2

now i expected Turo to play Qh5!, justifying the kNight sacrifice, but it didn't : it played dxe5? .. and after Kf7 Qh5+ Kg7, Black survived the attack ..

but Qh5+ is mate-in-3, isn't it ? : Qh5+ Kd7 {the only move} Bh3+ g4 {again the only move} Bxg4#
i count 6 plies, so why doesn't Morlock Turo find the mate ?

@tissatussa
Copy link
Author

NOTE: i just discovered at ply 7 the Turo version DOES play Qh5+ and mates .. so it's my misunderstanding of plies ?

@herohde
Copy link
Owner

herohde commented Aug 17, 2023

Thanks for reporting this issue. I would also expect it to find the mate at 6 ply (unless it ran out of time and cut it short or some such). Let me take a closer look -- do you have the PGN for the game? Or just the FEN?

@tissatussa
Copy link
Author

the first diagram is after 10...e5

the second diagram is after 11. Nxg5 fxg5

[Event "engine vs engine"]
[Site "Holland"]
[Date "2023.08.12"]
[Round "?"]
[White "Morlock v0.89.1.0 Turo ply6"]
[Black "ARBE dp6 ORG"]
[Result "1/2-1/2"]
[FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1"]
[GameDuration "00:11:04"]
[PlyCount "78"]
[SetUp "1"]
[TimeControl "1800"]

1. Nc3 {0.00/6 4.3s} Nc6 {2.7s} 2. d4 {0.00/6 5.3s} e6 {2.2s}
3. Nf3 {+0.01/6 25s} Bb4 {1.3s} 4. a3 {+0.43/6 8.7s} Bxc3+ {3.0s}
5. bxc3 {+1010.05/6 2.0s} d5 {1.6s} 6. Rg1 {+1010.10/6 18s} Qd6 {1.5s}
7. g3 {+1010.23/6 12s} f6 {6.3s} 8. a4 {+1010.31/6 15s} g5 {6.8s}
9. Ba3 {+1010.34/6 26s} Qd8 {4.3s} 10. e3 {+1010.35/6 7.3s} e5 {4.8s}
11. Nxg5 {+1040.19/6 20s} fxg5 {6.1s} 12. dxe5 {+M3/5 8.3s} Kf7 {13s}
13. Qh5+ {-1009.98/6 15s} Kg7 {4.0s} 14. f4 {-1010.09/6 20s} Bf5 {6.0s}
15. Rg2 {-1010.19/6 37s} a6 {10s} 16. fxg5 {-1009.88/6 45s} Qe8 {5.5s}
17. g4 {-1019.65/6 21s} Qxe5 {2.5s} 18. Kd2 {-1050.06/6 17s} Bg6 {12s}
19. Qh4 {-1030.20/6 23s} Re8 {12s} 20. Qg3 {-1020.96/6 26s} Qxg3 {16s}
21. Rxg3 {-1020.65/6 5.3s} Na5 {4.0s} 22. Bc5 {-1020.18/6 11s} Nc6 {3.4s}
23. h4 {-1020.33/6 18s} b6 {4.0s} 24. Ba3 {-1019.95/6 3.8s} Na5 {3.7s}
25. h5 {+0.01/6 6.0s} Be4 {1.6s} 26. Bxa6 {0.00/6 4.5s} Re5 {2.2s}
27. Rf1 {+1018.87/6 5.5s} c5 {3.7s} 28. h6+ {+0.09/6 4.6s} Kg6 {0.72s}
29. Rf8 {-1021.14/6 14s} Kxg5 {1.5s} 30. Bb2 {-1069.98/6 20s} Nc4+ {2.3s}
31. Kc1 {-1109.89/6 1.5s} Nxb2 {1.8s} 32. Kxb2 {-1109.97/6 3.0s} Kxh6 {1.5s}
33. Rb8 {-1109.95/6 5.2s} Kg5 {0.66s} 34. Rxb6 {-1059.97/6 3.4s} Nf6 {2.8s}
35. Be2 {-1060.75/6 4.6s} Ra8 {3.0s} 36. Rb5 {-1070.11/6 4.9s} Rc8 {3.7s}
37. Rb6 {-1060.77/6 9.4s} Ra8 {3.3s} 38. Rb5 {-1070.11/6 2.5s} Rc8 {3.8s}
39. Rb6 {-1060.77/6 6.2s} Ra8 {3.4s, Draw by 3-fold repetition} 1/2-1/2

@tissatussa
Copy link
Author

btw. while trying to reproduce this game, i let the Black engine (my own script) play against your Morlock Turo depth 6 again, and it seems Turo does not always play the same moves .. eg. its first move may be 1.d4 or 1.Nc3 .. also in the above game, move 15 (Rg2) can be Kd2 .. why does Morlock Turo does not play the same moves all the time? It's a simple engine ..

@tissatussa
Copy link
Author

btw. i did set a starting FEN, which is the normal starting position without castling rights, because "ARBE" v0.1 can not castle yet and it doesn't recognise such move made by the opponent ..

@herohde
Copy link
Owner

herohde commented Aug 19, 2023

Re different moves: I added a bit of randomness to Turochamp (and Sargon) evaluation to prevent them being deterministic and thus more fun for repeated play imo. You can remove that by modifying the setup here: https://github.com/herohde/morlock/blob/main/cmd/turochamp/main.go#L45.

The problem seems to be with the mate-in-X computation with the quiescence search and transposition tables. If I disable the transposition tables, I get the correct move. The console mode makes it easier to try:

$ go run cmd/turochamp/main.go
> console 
> nohash
> r r1bqk1nr/ppp4p/2n5/3pp1p1/P2P4/B1P1P1P1/2P2P1P/R2QKBR1 w Qkq - 0 12

    a   b   c   d   e   f   g   h
  ---------------------------------
8 | r |   | b | q | k |   | n | r | 
  ---------------------------------
7 | p | p | p |   |   |   |   | p | 
  ---------------------------------
6 |   |   | n |   |   |   |   |   | 
  ---------------------------------
5 |   |   |   | p | p |   | p |   | 
  ---------------------------------
4 | P |   |   | P |   |   |   |   | 
  ---------------------------------
3 | B |   | P |   | P |   | P |   | 
  ---------------------------------
2 |   |   | P |   |   | P |   | P | 
  ---------------------------------
1 | R |   |   | Q | K | B | R |   | 
  ---------------------------------
    a   b   c   d   e   f   g   h

fen:    r1bqk1nr/ppp4p/2n5/3pp1p1/P2P4/B1P1P1P1/2P2P1P/R2QKBR1 w Qkq - 0 12
result: ?, ply: 1, hash: 0xeef152bde16731b2

> d 6
> a
depth=1 score=-1038.60 nodes=50 time=4.300906ms hash=0% pv=Qd1-h5
depth=2 score=-1039.40 nodes=345 time=21.411804ms hash=0% pv=Qd1-h5 Ke8-d7
depth=3 score=-1038.50 nodes=2402 time=65.261841ms hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3
depth=4 score=M5 nodes=49491 time=1.335480111s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4
depth=5 score=M5 nodes=199584 time=5.045422388s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4 Bh3*g4
depth=6 score=M5 nodes=3602132 time=1m27.349761742s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4 Bh3*g4
bestmove Qd1-h5
Search, depth=6
  1. Qd1-h5	M5		(69474 nodes	pv Ke8-d7 Bf1-h3 g5-g4 Bh3*g4)
  2. f2-f4	-1010.21		(311843 nodes	pv h7-h5 d4*e5 Bc8-g4 Qd1-b1 Ra8-b8)
  3. d4*e5	-1039.58		(199740 nodes	pv Nc6*e5 Qd1-h5 Ne5-g6 Bf1-b5 c7-c6)
  4. h2-h4	-1039.79		(241903 nodes	pv h7-h5 Bf1-e2 g5-g4 d4*e5 Nc6*e5)
  5. Qd1-f3	-1039.82		(405633 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Bf1-b5 c7-c6)
  6. Bf1-b5	-1039.83		(54663 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
  7. Bf1-g2	-1039.87		(223037 nodes	pv Ng8-e7 Qd1-h5 Ne7-g6 Ke1-d2 Qd8-f6)
  8. h2-h3	-1039.89		(141418 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Ba3-b4 Ke8-f7)
  9. Ba3-c5	-1039.91		(210300 nodes	pv Ng8-f6 d4*e5 Nc6*e5 a4-a5 Ke8-f7)
 10. Bf1-e2	-1039.92		(269673 nodes	pv Qd8-f6 Be2-h5 Ke8-d8 d4*e5 Qf6*e5)
 11. Qd1-e2	-1039.92		(169694 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Qe2-b5 Ke8-f7)
 12. Bf1-d3	-1039.92		(175309 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Bd3-b5 Ke8-f7)
 13. Rg1-g2	-1039.93		(143828 nodes	pv h7-h5 Bf1-e2 Ng8-f6 d4*e5 Nc6*e5)
 14. a4-a5	-1039.94		(193908 nodes	pv h7-h5 d4*e5 Nc6*e5 h2-h3 Ng8-e7)
 15. Rg1-h1	-1039.95		(220394 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Ba3-b4 Ke8-f7)
 16. Ra1-b1	-1040.01		(204191 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
 17. Ba3-c1	-1040.05		(147643 nodes	pv Ng8-e7 Qd1-h5 Ne7-g6 Bc1-a3 Qd8-f6)
 18. Ba3-b2	-1040.05		(139512 nodes	pv h7-h5 d4*e5 Nc6*e5 Bb2-a3 Bc8-g4)
 19. Ra1-a2	-1040.11		(218333 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
 20. e3-e4	-1040.11		(166723 nodes	pv h7-h5 Bf1-e2 Ng8-f6 e4*d5 Qd8*d5)
 21. Ra1-c1	-1040.12		(163964 nodes	pv h7-h5 d4*e5 Nc6*e5 Bf1-b5 c7-c6)
 22. Qd1-b1	-1040.16		(125701 nodes	pv e5*d4 c3*d4 Qd8-f6 Qb1-b5 Ng8-e7)
 23. Qd1-d3	-1040.16		(129544 nodes	pv e5*d4 c3*d4 Qd8-f6 Qd3-b5 Ng8-e7)
 24. Qd1-d2	-1040.16		(102947 nodes	pv Qd8-f6 Bf1-b5 Ng8-e7 d4*e5 Qf6*e5)
 25. g3-g4	-1040.18		(90576 nodes	pv e5*d4 c3*d4 Qd8-f6 Bf1-b5 Ng8-e7)
 26. f2-f3	-1040.21		(81617 nodes	pv e5*d4 c3*d4 Qd8-f6 Bf1-b5 Ng8-e7)
 27. Qd1-c1	-1040.27		(101933 nodes	pv Qd8-f6 Bf1-b5 e5*d4 c3*d4 Ng8-e7)
 28. Ke1-d2	-1040.35		(202397 nodes	pv Qd8-f6 Qd1-e1 Ng8-e7 Bf1-b5 Bc8-d7)
 29. Ke1-e2	-1040.58		(106035 nodes	pv e5*d4 c3*d4 Qd8-f6 Ke2-e1 Ng8-e7)
 30. c3-c4	-1040.81		(194569 nodes	pv g5-g4 c4*d5 Qd8*d5 c2-c4 Qd5-a5)
 31. Bf1-h3	-1049.76		(98291 nodes	pv Bc8*h3 Qd1-h5 Ke8-d7 Qh5*h3 Kd7-e8)
 32. Ba3-b4	-1069.51		(84190 nodes	pv Nc6*b4 c3*b4 e5*d4 Bf1-b5 c7-c6)
 33. Bf1-c4	-1129.90		(137836 nodes	pv d5*c4 Qd1-h5 Ke8-d7 Qh5-f7 Ng8-e7)
 34. Bf1-a6	-1159.72		(75964 nodes	pv b7*a6 Qd1-h5 Ke8-d7 d4*e5 Nc6*e5)
 35. Ba3-f8	-1160.05		(82640 nodes	pv Ke8*f8 Qd1-f3 Kf8-g7 d4*e5 Nc6*e5)
 36. Ba3-d6	-1160.21		(89358 nodes	pv Qd8*d6 d4*e5 Qd6*e5 Qd1-h5 Ke8-d8)
 37. Ba3-e7	-1160.27		(70939 nodes	pv Ng8*e7 Qd1-h5 Ne7-g6 d4*e5 Nc6*e5)
 38. Qd1-g4	-1480.21		(20485 nodes	pv Bc8*g4 h2-h3 Bg4-f5 d4*e5 Bf5*c2)

Turochamp searches captures as a "considerable move", so it finds the mate at depth 4. A deeper search can't improve on a mate in 5 ply (M5).

I can repro the poor move, if I do a prior search from r1bqk1nr/ppp4p/2n2p2/3pp1p1/P2P4/B1P1PNP1/2P2P1P/R2QKBR1 w Qkq - 0 11 first with transposition tables. Then I get an incorrect mate in 3 ply (M3) with the bad move you saw in your game (it's in the PGN as well: 12. dxe5 {+M3/5 8.3s} Kf7 {13s}), yet it is not confirmed by the breakdown:

    a   b   c   d   e   f   g   h
  ---------------------------------
8 | r |   | b | q | k |   | n | r | 
  ---------------------------------
7 | p | p | p |   |   |   |   | p | 
  ---------------------------------
6 |   |   | n |   |   |   |   |   | 
  ---------------------------------
5 |   |   |   | p | p |   | p |   | 
  ---------------------------------
4 | P |   |   | P |   |   |   |   | 
  ---------------------------------
3 | B |   | P |   | P |   | P |   | 
  ---------------------------------
2 |   |   | P |   |   | P |   | P | 
  ---------------------------------
1 | R |   |   | Q | K | B | R |   | 
  ---------------------------------
    a   b   c   d   e   f   g   h

fen:    r1bqk1nr/ppp4p/2n5/3pp1p1/P2P4/B1P1P1P1/2P2P1P/R2QKBR1 w Qkq - 0 12
result: ?, ply: 3, hash: 0xeef152bde16731b2

a
depth=1 score=-1038.60 nodes=43 time=2.609044ms hash=1% pv=Qd1-h5
depth=2 score=-1039.17 nodes=223 time=12.552893ms hash=1% pv=Qd1-e2 e5*d4
depth=3 score=-1038.50 nodes=1922 time=52.052052ms hash=1% pv=Qd1-h5 Ke8-d7 Bf1-h3
depth=4 score=M5 nodes=6412 time=148.789079ms hash=1% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4
depth=5 score=M3 nodes=254302 time=5.721763514s hash=2% pv=d4*e5 Bc8-d7 Qd1-h5.             <-------------
bestmove d4*e5
Search, depth=5
  1. Qd1-h5	M5		(4743 nodes	pv Ke8-d7 Bf1-h3 g5-g4 Bh3*g4)
  2. d4*e5	-1038.61		(28778 nodes	pv Nc6*e5 Bf1-b5 c7-c6 Qd1-h5)
  3. Bf1-e2	-1038.90		(29016 nodes	pv Ng8-e7 d4*e5 Nc6*e5 Be2-h5)
  4. Bf1-b5	-1038.95		(11415 nodes	pv e5*d4 e3*d4 Ng8-e7 Qd1-h5)
  5. Qd1-e2	-1038.97		(17224 nodes	pv e5*d4 e3*d4 Ng8-e7 Qe2-h5)
  6. h2-h3	-1039.20		(15396 nodes	pv e5*d4 e3*d4 h7-h5 Qd1-e2)
  7. f2-f4	-1039.33		(19517 nodes	pv e5*f4 Qd1-h5 Ke8-d7 g3*f4)
  8. h2-h4	-1039.62		(15883 nodes	pv h7-h5 d4*e5 g5*h4 Bf1-b5)
  9. Ba3-c5	-1039.67		(22798 nodes	pv Ng8-f6 d4*e5 Nf6-g4 f2-f4)
 10. Qd1-f3	-1039.67		(25524 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bf1-b5)
 11. Bf1-g2	-1039.68		(15898 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Qd1-d4)
 12. Bf1-d3	-1039.72		(32883 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bd3-b5)
 13. Rg1-g2	-1039.77		(21264 nodes	pv Ng8-f6 d4*e5 Nf6-g4 f2-f4)
 14. Rg1-h1	-1039.78		(20417 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bf1-b5)
 15. Qd1-d3	-1039.79		(21079 nodes	pv e5*d4 e3*d4 Ng8-e7 Qd3-e3)
 16. Qd1-d2	-1039.81		(17472 nodes	pv Ng8-f6 Bf1-b5 Nf6-e4 Qd2-d3)
 17. Qd1-b1	-1039.81		(13905 nodes	pv e5*d4 c3*d4 Ng8-e7 Qb1-b5)
 18. Ra1-b1	-1039.83		(20703 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bf1-b5)
 19. Qd1-c1	-1039.89		(20422 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qc1-b2)
 20. c3-c4	-1039.92		(13705 nodes	pv h7-h5 Qd1-f3 Ng8-f6 d4*e5)
 21. Ra1-a2	-1039.93		(20028 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bf1-b5)
 22. f2-f3	-1039.94		(10110 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-d2)
 23. Ba3-b2	-1039.96		(18082 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bb2-a3)
 24. Ba3-c1	-1039.96		(14563 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bc1-a3)
 25. Ra1-c1	-1039.96		(17201 nodes	pv Ng8-f6 d4*e5 Nf6-g4 Bf1-b5)
 26. g3-g4	-1040.01		(14960 nodes	pv Qd8-f6 Bf1-b5 Ng8-e7 Qd1-d3)
 27. Ke1-d2	-1040.01		(26420 nodes	pv Ng8-f6 d4*e5 Nf6-e4 Kd2-e1)
 28. Ke1-e2	-1040.18		(8030 nodes	pv e5*d4 c3*d4 Ng8-e7 Qd1-d3)
 29. Bf1-h3	-1048.94		(14635 nodes	pv Bc8*h3 Qd1-h5 Ke8-d7 Qh5*h3)
 30. Ba3-b4	-1068.50		(12306 nodes	pv e5*d4 Qd1-h5 Ke8-d7 Bf1-h3)
 31. a4-a5	-1068.53		(8147 nodes	pv e5*d4 Qd1-h5 Ke8-d7 Bf1-h3)
 32. e3-e4	-1068.54		(10187 nodes	pv d5*e4 Qd1-h5 Ke8-d7 Bf1-h3)
 33. Bf1-a6	-1159.00		(7674 nodes	pv b7*a6 Qd1-h5 Ke8-d7 Qh5-g4)
 34. Bf1-c4	-1159.01		(8972 nodes	pv d5*c4 Qd1-h5 Ke8-d7 Qh5-g4)
 35. Ba3-d6	-1159.16		(8048 nodes	pv Qd8*d6 d4*e5 Nc6*e5 Qd1-h5)
 36. Ba3-f8	-1159.80		(7892 nodes	pv Ke8*f8 d4*e5 Nc6*e5 Qd1-d4)
 37. Ba3-e7	-1159.82		(10698 nodes	pv Ke8*e7 d4*e5 Nc6*e5 Qd1-d4)
 38. Qd1-g4	-1460.30		(4722 nodes	pv Bc8*g4 h2-h3 Bg4-f5 Ke1-d2)

I'll look closer into that bug. Thanks for reporting it.

@tissatussa
Copy link
Author

Thanks for your time to investigate this, i thought you could be curious to find the cause of this Issue, because you're the creator of this script.

Indeed randomness is more fun for repeated play, but I have no objection when your TuroChamp version strictly implements the original evaluation rule and thus plays the same moves all the time. Users might even expect that, eg. for evaluation of those original rules in certain positions. Therefor i suggest you create an UCI option for a parameter like "add some randomness" ? I know such UCI (checkbox, selectbox, etc) options are easy to code, and CuteChess nicely displays them in its settings pane. Other UCI options might be Depth, logging On/Off, and even selecting a different set of evaluation values ?

@herohde
Copy link
Owner

herohde commented Sep 17, 2023

Appreciate it. Thanks for the suggestion. Depth and Noise (= evaluation randomness) are now UCI options for convenience.

@tissatussa
Copy link
Author

..Depth and Noise (= evaluation randomness) are now UCI options..

i really like your newest v0.89.2.0 : those UCI options for Depth and Noise are awesome !
at first i built the Turochamp engine .. to make it work, i had to use the gvm tool (i'm on Linux) to install and set a proper GO version : i got a valid binary of 2.7 Mb :

uci
id name TUROCHAMP (1948) 0.89.2.0.nohash
id author Alan Turing and David Champernowne
option name Depth type spin default 2 min 0 max 100
option name Hash type spin default 0 min 0 max 16384
option name Noise type spin default 10 min 0 max 10000
uciok

then i did some tests in CuteChess, using 13 min + 10 sec bonus, setting Depth 6, 7 and even 8, and Turochamp played well against some (weak) engines .. i see Noise can be set 0 upto 10000, but why default 10 ? what does it mean ? i set Noise 5000 (the half of your max) and just watch the games evolving : no obvious mistakes were made, so i guess that Noise feature picks moves which "are also" good - or not bad : how does Noise work, can you elaborate on this ? does this feature still resemble the Turochamp principe ?

about the Depth option : using your previous v0.89.1.0 i had to build binaries with custom depth by adjusting this value in the source code .. now this option can be set in the (CuteChess) GUI options pane, which indeed is very convenient .. with my time control, Turochamp seems to keep its move-time below 30 seconds, even with Depth 8 : so i guess some max-time-per-move is used ? and why can Turochamp only reach higher depths after a lot of time, unlike many other engines ? does it have simple / poor pruning ? -- respect though..

these are just some questions and remarks.
can you tell us your ideas to implement these Morlock engines, esp. the Turochamp version ? Btw. i like the original Turochamp PDF document!

@herohde
Copy link
Owner

herohde commented Sep 24, 2023

Glad that it was helpful!

Re noise: The engine uses an evaluation score in "pawns" as a nominal value. The noise adds a randomness in milli-pawns. So 1,000 noise means +/- 0.5 pawns. The UCI option unfortunately does not allows an inline description to these options.

However, as you can tell from reading the original paper, Turochamp does not use "pawns" as a scoring value, but rather the tuple of (material ratio, position play). The implementation here combines them into a "pawns" score but it is in reality not in pawns: see https://github.com/herohde/morlock/blob/main/cmd/turochamp/turochamp/eval.go#L20. The scoring is also made more symmetrical to make it more stable and work with odd search depths. The (arbitrary) UCI maximum of 10k is indeed small compared to the material ratio. But larger noise will drown out position play.

Re depth: The time control assumes that there are 40 moves left in the game to manage time, see https://github.com/herohde/morlock/blob/main/pkg/search/searchctl/timectrl.go#L26. This simple heuristic makes it hard to run out of time, but is overly conservative later in the game.

The search implementation is indeed not very sophisticated. I found it more enjoyable to to focus on the low depths, where search does not hide the engines' quirks. At low ply, search efficiency does not matter. Also, Sargon has some score factors that are relative to the root position, which makes transposition table scores unreliable to reuse from past moves. In other words, these old engines have some features that do not fit easily into modern search optimizations. Turochamp specifically uses an unbounded quiescence search of "considerable moves", which may be expensive. Sargon similarly has a non-standard quiescence search heuristic.

Not sure I understand your last question. Can you elaborate?

@tissatussa
Copy link
Author

tissatussa commented Sep 24, 2023

thanks for the extensive reply and insights, it's also valuable info for other users, reading about this (i could have created a seperate Issue for it?).

my last question .. you mean tell us your ideas to implement these Morlock engines, esp. the Turochamp version ? well, i guess Turin didn't use recursion upto depth 6 or so, while calculating on paper .. so did you add some own ideas into this, eg. handling odd plies ? (i see the node counts in CuteChess sometimes show very low -30 or so- at some odd depth ? while normally the node count always goes up while reaching higher depths.

i also have my own ideas .. i could tweak the evaluation (not the search) with some own factors, like PSTs .. i'm not familiar with GO though .. maybe i should use the Nim version, a language i learned lately .. btw. i must yet read those linked docs.

@herohde
Copy link
Owner

herohde commented Sep 24, 2023

Gotcha. My goal with Turochamp (and Sargon) was to implement it as faithfully as possible to the paper, but in a more standard engine framework. The only tweak I really made was to make the position-play evaluation symmetrical and fit the heuristics into a signed "pawns" score. The symmetry tweak was to counter some overly dubious moves at ply 1 that made it less fun, if I recall correctly, not improve the evaluation per se.

@tissatussa
Copy link
Author

tissatussa commented Sep 25, 2023

overall your explanation is clear to me, and valuable ! Sounds like you did a lot of experiments and tests to get proper results. Btw. for now i only focus on the Turochamp engine, i understand those Rules Turin described in his paper and i think i agree .. i'm rather surprised how well your version plays with higher depth setting - myself i can hardly win .. after my tests i tend to conclude its rating is about 1300 - me 1800 !?

about the "pawns" score : it seems (when using Noise 5000) the engine gives eval values upto around +-0.6 (cp?) and often at some point those figures get 1000 upto 5000 (when winning) .. this is curious : did my Noise 5000 cause these values ? Is Noise some treshold ? i don't fully understand these values, i expect 0.6 will be followed by 1.0 upto 5.0 in that case, or is this a mis-interpretation of the CuteChess GUI ?

by threshold i mean : when Noise is high, even a move with an eval less then that threshold could become bestmove ? Is your Noise value some "Contempt", as used by other authors, or a different concept ? In that case we could try to construct something like "Advisors", giving their own stats which can influence bestmove when the eval of their suggestion is within that treshold ?

this is my idea in a nutshell .. are you willing to discuss such further ? i can open an Issue for it.

@herohde
Copy link
Owner

herohde commented Sep 25, 2023

I realized that I broke the noise functionality when I moved it around for UCI. The noise option had no effect. That's now fixed. Sorry about causing confusion.

The score values for Turochamp don't fit the usual pawn interpretation. For example, black to move with the white queen en prise:

    a   b   c   d   e   f   g   h
  ---------------------------------
8 | r | n | b | q | k | b | n | r | 
  ---------------------------------
7 | p | p | p |   | p | p | p | p | 
  ---------------------------------
6 |   |   |   | p |   |   |   |   | 
  ---------------------------------
5 |   |   |   |   |   |   |   |   | 
  ---------------------------------
4 |   |   |   |   |   |   | Q |   | 
  ---------------------------------
3 |   |   |   |   | P |   |   |   | 
  ---------------------------------
2 | P | P | P | P |   | P | P | P | 
  ---------------------------------
1 | R | N | B |   | K | B | N | R | 
  ---------------------------------
    a   b   c   d   e   f   g   h

fen:    rnbqkbnr/ppp1pppp/3p4/8/6Q1/4P3/PPPP1PPP/RNB1KBNR b KQkq - 1 2
result: ?, ply: 4, hash: 0x65bd7a29073de7e7

a 1
depth=1 score=1320.34 nodes=27 time=3.039988ms hash=0% pv=Bc8*g4
bestmove Bc8*g4
Search, depth=1
  1. Bc8*g4	1320.34		(1 nodes	pv )
  2. e7-e5	-0.09		(1 nodes	pv )
  3. Nb8-c6	-0.11		(1 nodes	pv )
  4. e7-e6	-0.12		(1 nodes	pv )
  5. Bc8-e6	-0.13		(1 nodes	pv )
  6. Bc8-d7	-0.13		(1 nodes	pv )
  7. Ng8-f6	-0.14		(1 nodes	pv )
  8. Ng8-h6	-0.20		(1 nodes	pv )
  9. c7-c6	-0.22		(1 nodes	pv )
 10. a7-a5	-0.23		(1 nodes	pv )
 11. h7-h5	-0.24		(1 nodes	pv )
 12. Nb8-d7	-0.25		(1 nodes	pv )
 13. Qd8-d7	-0.27		(1 nodes	pv )
 14. g7-g6	-0.27		(1 nodes	pv )
 15. Nb8-a6	-0.28		(1 nodes	pv )
 16. c7-c5	-0.30		(1 nodes	pv )
 17. h7-h6	-0.33		(1 nodes	pv )
 18. a7-a6	-0.34		(1 nodes	pv )
 19. f7-f5	-0.34		(1 nodes	pv )
 20. d6-d5	-0.35		(1 nodes	pv )
 21. b7-b6	-0.38		(1 nodes	pv )
 22. f7-f6	-0.39		(1 nodes	pv )
 23. g7-g5	-1020.20		(2 nodes	pv )
 24. b7-b5	-1020.75		(2 nodes	pv )
 25. Bc8-f5	-1090.70		(2 nodes	pv )

The scores are from blacks point of view in pawns, where positive is ahead. Taking the queen is vastly better than any other move, but obviously not worth more than 1000 pawns (most engines would score it as ~9 pawns ahead). That is just an artifact of combining "material ratio" and "position play" difference into a single score, where the ratio always dominates. The ratio of 1.32 is encoded as 1320 pawns and the position play score of 3.4 is encoded as 0.34. Even losing a single pawn with g7-g5, for example, bring a losing -1.02 ration -- expressed as -1020 "pawns". This is where the modern emphasis on scoring everything in "pawns" clash with Turing's design.

Back to noise: the values are quite close -- they are often just a few centi-pawn apart the way the score is combined. The noise random element just aims vary the play. It's not contempt or anything clever. If noise is high enough, any move can be the best move and the play is random. The starting position:

    a   b   c   d   e   f   g   h
  ---------------------------------
8 | r | n | b | q | k | b | n | r | 
  ---------------------------------
7 | p | p | p | p | p | p | p | p | 
  ---------------------------------
6 |   |   |   |   |   |   |   |   | 
  ---------------------------------
5 |   |   |   |   |   |   |   |   | 
  ---------------------------------
4 |   |   |   |   |   |   |   |   | 
  ---------------------------------
3 |   |   |   |   |   |   |   |   | 
  ---------------------------------
2 | P | P | P | P | P | P | P | P | 
  ---------------------------------
1 | R | N | B | Q | K | B | N | R | 
  ---------------------------------
    a   b   c   d   e   f   g   h

fen:    rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
result: ?, ply: 1, hash: 0xc73b6db27699f0b0

a 1
depth=1 score=0.44 nodes=21 time=994.935µs hash=0% pv=e2-e3
bestmove e2-e3
Search, depth=1
  1. e2-e3	0.44		(1 nodes	pv )
  2. e2-e4	0.42		(1 nodes	pv )
  3. d2-d4	0.33		(1 nodes	pv )
  4. d2-d3	0.27		(1 nodes	pv )
  5. Ng1-f3	0.23		(1 nodes	pv )
  6. Nb1-c3	0.23		(1 nodes	pv )
  7. h2-h4	0.18		(1 nodes	pv )
  8. a2-a4	0.18		(1 nodes	pv )
  9. Ng1-h3	0.18		(1 nodes	pv )
 10. c2-c4	0.18		(1 nodes	pv )
 11. Nb1-a3	0.18		(1 nodes	pv )
 12. c2-c3	0.15		(1 nodes	pv )
 13. b2-b4	0.15		(1 nodes	pv )
 14. g2-g4	0.15		(1 nodes	pv )
 15. g2-g3	0.13		(1 nodes	pv )
 16. b2-b3	0.13		(1 nodes	pv )
 17. h2-h3	0.08		(1 nodes	pv )
 18. a2-a3	0.08		(1 nodes	pv )
 19. f2-f4	-0.06		(1 nodes	pv )
 20. f2-f3	-0.09		(1 nodes	pv )

Using noise of 100 (= +/- 5 centipawns), for example, either e2-e3 or e2-e4 could be the initial best move. (Note that the console mode breakdown does not use noise or transposition tables, even if the actual search does.)

@tissatussa
Copy link
Author

regarding Turochamp : in main.go line 24 i see :

usage: turochamp [options]

how can we see this output in console ?
you showed some output diagrams and info, regarding "console mode breakdown" .. what is that ? How can i reproduce your output ? I just did uci, and commands like go depth #, but eg. help, info, display etc. seem invalid commands, indeed non-UCI afaik. Which [options] do we have ? Btw. i expected the code of the function flag.PrintDefaults() would give me answers, but it's not there, being imported by "flag" !? (i'm not into GO programming)

@herohde
Copy link
Owner

herohde commented Sep 26, 2023

You can see the command line options by passing -h as a command line argument:

$ go run cmd/turochamp/main.go -h
usage: turochamp [options]

TUROCHAMP is a re-implementation of Alan Turing and David Champernowne's 1948
chess engine, described in "Digital computers applied to games" (1953). The
re-implementation uses the UCI protocol for use in modern chess programs.
Options:
  -alsologtostderr
    	log to standard error as well as files
  -log_backtrace_at value
    	when logging hits line file:N, emit a stack trace
  -log_dir string
    	If non-empty, write log files in this directory
  -logtostderr
    	log to standard error instead of files
  -noise uint
    	Evaluation noise in "millipawns" (zero if deterministic) (default 10)
  -ply uint
    	Search depth limit (zero if no limit) (default 2)
  -stderrthreshold value
    	logs at or above this threshold go to stderr
  -v value
    	log level for V logs
  -vmodule value
    	comma-separated list of pattern=N settings for file-filtered logging

You can set the noise and ply defaults via the command line. The other are logging settings.

You can use the console mode by passing console instead of uci as the first input. It's mainly for internal development use and supports various commands as defined here: https://github.com/herohde/morlock/blob/main/pkg/engine/console/console.go#L74.

In a previous comment, I indicated some commands in that mode with > :

$ go run cmd/turochamp/main.go
> console 
> r r1bqk1nr/ppp4p/2n5/3pp1p1/P2P4/B1P1P1P1/2P2P1P/R2QKBR1 w Qkq - 0 12

    a   b   c   d   e   f   g   h
  ---------------------------------
8 | r |   | b | q | k |   | n | r | 
  ---------------------------------
7 | p | p | p |   |   |   |   | p | 
  ---------------------------------
6 |   |   | n |   |   |   |   |   | 
  ---------------------------------
5 |   |   |   | p | p |   | p |   | 
  ---------------------------------
4 | P |   |   | P |   |   |   |   | 
  ---------------------------------
3 | B |   | P |   | P |   | P |   | 
  ---------------------------------
2 |   |   | P |   |   | P |   | P | 
  ---------------------------------
1 | R |   |   | Q | K | B | R |   | 
  ---------------------------------
    a   b   c   d   e   f   g   h

fen:    r1bqk1nr/ppp4p/2n5/3pp1p1/P2P4/B1P1P1P1/2P2P1P/R2QKBR1 w Qkq - 0 12
result: ?, ply: 1, hash: 0xeef152bde16731b2

> d 6
> a
depth=1 score=-1038.60 nodes=50 time=4.300906ms hash=0% pv=Qd1-h5
depth=2 score=-1039.40 nodes=345 time=21.411804ms hash=0% pv=Qd1-h5 Ke8-d7
depth=3 score=-1038.50 nodes=2402 time=65.261841ms hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3
depth=4 score=M5 nodes=49491 time=1.335480111s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4
depth=5 score=M5 nodes=199584 time=5.045422388s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4 Bh3*g4
depth=6 score=M5 nodes=3602132 time=1m27.349761742s hash=0% pv=Qd1-h5 Ke8-d7 Bf1-h3 g5-g4 Bh3*g4
bestmove Qd1-h5
Search, depth=6
  1. Qd1-h5	M5		(69474 nodes	pv Ke8-d7 Bf1-h3 g5-g4 Bh3*g4)
  2. f2-f4	-1010.21		(311843 nodes	pv h7-h5 d4*e5 Bc8-g4 Qd1-b1 Ra8-b8)
  3. d4*e5	-1039.58		(199740 nodes	pv Nc6*e5 Qd1-h5 Ne5-g6 Bf1-b5 c7-c6)
  4. h2-h4	-1039.79		(241903 nodes	pv h7-h5 Bf1-e2 g5-g4 d4*e5 Nc6*e5)
  5. Qd1-f3	-1039.82		(405633 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Bf1-b5 c7-c6)
  6. Bf1-b5	-1039.83		(54663 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
  7. Bf1-g2	-1039.87		(223037 nodes	pv Ng8-e7 Qd1-h5 Ne7-g6 Ke1-d2 Qd8-f6)
  8. h2-h3	-1039.89		(141418 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Ba3-b4 Ke8-f7)
  9. Ba3-c5	-1039.91		(210300 nodes	pv Ng8-f6 d4*e5 Nc6*e5 a4-a5 Ke8-f7)
 10. Bf1-e2	-1039.92		(269673 nodes	pv Qd8-f6 Be2-h5 Ke8-d8 d4*e5 Qf6*e5)
 11. Qd1-e2	-1039.92		(169694 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Qe2-b5 Ke8-f7)
 12. Bf1-d3	-1039.92		(175309 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Bd3-b5 Ke8-f7)
 13. Rg1-g2	-1039.93		(143828 nodes	pv h7-h5 Bf1-e2 Ng8-f6 d4*e5 Nc6*e5)
 14. a4-a5	-1039.94		(193908 nodes	pv h7-h5 d4*e5 Nc6*e5 h2-h3 Ng8-e7)
 15. Rg1-h1	-1039.95		(220394 nodes	pv Ng8-f6 d4*e5 Nc6*e5 Ba3-b4 Ke8-f7)
 16. Ra1-b1	-1040.01		(204191 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
 17. Ba3-c1	-1040.05		(147643 nodes	pv Ng8-e7 Qd1-h5 Ne7-g6 Bc1-a3 Qd8-f6)
 18. Ba3-b2	-1040.05		(139512 nodes	pv h7-h5 d4*e5 Nc6*e5 Bb2-a3 Bc8-g4)
 19. Ra1-a2	-1040.11		(218333 nodes	pv Qd8-f6 d4*e5 Qf6*e5 Qd1-h5 Ke8-d8)
 20. e3-e4	-1040.11		(166723 nodes	pv h7-h5 Bf1-e2 Ng8-f6 e4*d5 Qd8*d5)
 21. Ra1-c1	-1040.12		(163964 nodes	pv h7-h5 d4*e5 Nc6*e5 Bf1-b5 c7-c6)
 22. Qd1-b1	-1040.16		(125701 nodes	pv e5*d4 c3*d4 Qd8-f6 Qb1-b5 Ng8-e7)
 23. Qd1-d3	-1040.16		(129544 nodes	pv e5*d4 c3*d4 Qd8-f6 Qd3-b5 Ng8-e7)
 24. Qd1-d2	-1040.16		(102947 nodes	pv Qd8-f6 Bf1-b5 Ng8-e7 d4*e5 Qf6*e5)
 25. g3-g4	-1040.18		(90576 nodes	pv e5*d4 c3*d4 Qd8-f6 Bf1-b5 Ng8-e7)
 26. f2-f3	-1040.21		(81617 nodes	pv e5*d4 c3*d4 Qd8-f6 Bf1-b5 Ng8-e7)
 27. Qd1-c1	-1040.27		(101933 nodes	pv Qd8-f6 Bf1-b5 e5*d4 c3*d4 Ng8-e7)
 28. Ke1-d2	-1040.35		(202397 nodes	pv Qd8-f6 Qd1-e1 Ng8-e7 Bf1-b5 Bc8-d7)
 29. Ke1-e2	-1040.58		(106035 nodes	pv e5*d4 c3*d4 Qd8-f6 Ke2-e1 Ng8-e7)
 30. c3-c4	-1040.81		(194569 nodes	pv g5-g4 c4*d5 Qd8*d5 c2-c4 Qd5-a5)
 31. Bf1-h3	-1049.76		(98291 nodes	pv Bc8*h3 Qd1-h5 Ke8-d7 Qh5*h3 Kd7-e8)
 32. Ba3-b4	-1069.51		(84190 nodes	pv Nc6*b4 c3*b4 e5*d4 Bf1-b5 c7-c6)
 33. Bf1-c4	-1129.90		(137836 nodes	pv d5*c4 Qd1-h5 Ke8-d7 Qh5-f7 Ng8-e7)
 34. Bf1-a6	-1159.72		(75964 nodes	pv b7*a6 Qd1-h5 Ke8-d7 d4*e5 Nc6*e5)
 35. Ba3-f8	-1160.05		(82640 nodes	pv Ke8*f8 Qd1-f3 Kf8-g7 d4*e5 Nc6*e5)
 36. Ba3-d6	-1160.21		(89358 nodes	pv Qd8*d6 d4*e5 Qd6*e5 Qd1-h5 Ke8-d8)
 37. Ba3-e7	-1160.27		(70939 nodes	pv Ng8*e7 Qd1-h5 Ne7-g6 d4*e5 Nc6*e5)
 38. Qd1-g4	-1480.21		(20485 nodes	pv Bc8*g4 h2-h3 Bg4-f5 d4*e5 Bf5*c2)

@tissatussa
Copy link
Author

nice ! this is exactly what i hoped for .. so "a" is "analyse" .. that explains your output, thanks!

[ i decided to close this Issue now, our info tends to go beyond the subject ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants