python-chess on cartesi
commit
d6f4b4f3ea
|
@ -0,0 +1 @@
|
|||
*.ext2
|
|
@ -0,0 +1,22 @@
|
|||
# Cartesi python-chess
|
||||
Crufty scripts to build disk images to run under the Cartesi
|
||||
RISC-V machine emulator that verify a chess game. Similar
|
||||
to the Cartesi example, but this is in python using python-chess,
|
||||
not javascript.
|
||||
|
||||
|
||||
# Upstream
|
||||
|
||||
## Python Chess
|
||||
|
||||
* https://python-chess.readthedocs.io/en/latest/
|
||||
|
||||
* https://github.com/niklasf/python-chess/
|
||||
|
||||
# # Cartesi
|
||||
|
||||
* https://cartesi.io/docs/intro
|
||||
|
||||
* https://github.com/cartesi/poker/tree/master/blockchain/verifier/chess
|
||||
|
||||
* https://medium.com/cartesi/how-cartesi-is-changing-the-game-showcasing-chess-9f4e39d5cea0
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Make disk image with script
|
||||
genext2fs -b 1024 -d cartesi-python-chess-cartesi-img cartesi-python-chess.ext2
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
|
||||
/mnt/cartesi-python-chess/python-chess-validate.py
|
||||
|
||||
exit
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
[Event "Grand Slam Final Masters"]
|
||||
[Site "Bilbao ESP"]
|
||||
[Date "2010.10.11"]
|
||||
[Round "3"]
|
||||
[White "Shirov, Alexei"]
|
||||
[Black "Carlsen, Magnus"]
|
||||
[Result "1/2-1/2"]
|
||||
[WhiteTitle "GM"]
|
||||
[BlackTitle "GM"]
|
||||
[WhiteElo "2749"]
|
||||
[BlackElo "2826"]
|
||||
[ECO "C95"]
|
||||
[Opening "Ruy Lopez"]
|
||||
[Variation "closed, Breyer, Borisenko variation"]
|
||||
[WhiteFideId "2209390"]
|
||||
[BlackFideId "1503014"]
|
||||
[EventDate "2010.10.09"]
|
||||
[EventType "DRR"]
|
||||
|
||||
1. e4 e5 2. Nf3 Nc8 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3
|
||||
O-O 9. h3 Nb8 10. d4 Nbd7 11. Nbd2 Bb7 12. Bc2 Re8 13. a4 Bf8 14. Bd3 c6 15. b4
|
||||
Nb6 16. axb5 cxb5 17. d5 Rc8 18. Bb2 Nh5 19. Bf1 f5 20. Nxe5 Rxe5 21. c4 Nf6 22.
|
||||
Bxe5 dxe5 23. c5 fxe4 24. d6 Na4 25. Nc4 Nxc5 26. bxc5 Rxc5 27. Qb3 Bd5 28. Qb4
|
||||
Rxc4 29. Bxc4 bxc4 30. Rxa6 Qc8 31. Qa5 c3 32. d7 Qxd7 33. Qxc3 Qb7 34. Rea1 Qb8
|
||||
35. Ra7 h6 36. Rc7 Qb6 37. Qxe5 Bd6 38. Rc8+ Kf7 39. Qc3 Qb7 40. Rca8 Qxa8 41.
|
||||
Rxa8 Bxa8 42. Qd4 Bd5 43. Qa7+ Be7 44. Qc7 h5 45. Qe5 g6 46. Kh2 Be6 47. Kg1 Bf5
|
||||
48. Kf1 Ne8 49. Kg1 Ng7 50. Qd5+ Ne6 51. Qb7 h4 52. Kh2 Nf4 53. Kg1 Nd3 54. Kf1
|
||||
Nc5 55. Qd5+ Be6 56. Qe5 Bf5 57. Qd5+ Ne6 58. Qb7 Kf8 59. Qa8+ Bd8 60. Qa7 Bf6
|
||||
61. Qb7 Kg8 62. Qa7 Bg5 63. Ke2 Nf4+ 64. Kf1 Nh5 65. Ke2 Kf8 66. Kf1 Bf6 67. Qc7
|
||||
Ng7 68. Qa7 Ne6 69. Qb7 Nd8 70. Qa7 Nf7 71. Kg1 Kg7 72. Kf1 Be5 73. Qe7 g5 74.
|
||||
Kg1 Bf6 75. Qb7 Kg6 76. Qd5 Ne5 77. Qg8+ Bg7 78. Qe8+ Kh6 79. Qe7 Nd3 80. Kf1
|
||||
Nf4 81. Qd6+ Bg6 82. Qe7 Nd5 83. Qe6 Nf6 84. Kg1 Be8 85. Qf5 Bd7 86. Qe5 Kg6 87.
|
||||
Kf1 Bf8 88. Kg1 Ba3 89. Qc7 Bb4 90. Qe5 Bd2 91. Qd4 Bf4 92. Qb6 Be8 93. Kf1 Bf7
|
||||
94. Kg1 Kf5 95. Qa7 Be6 96. Kf1 Kg6 97. Qb6 Bd7 98. Kg1 Ba4 99. Qe6 Bb5 100. Qb6
|
||||
Bc4 101. Qd4 Be6 102. Kf1 Bf5 103. Kg1 g4 104. hxg4 Bxg4 105. Qc3 Bf5 106. Qb3
|
||||
Bg5 107. Kf1 Kh6 108. Kg1 Kg6 109. Kf1 Bd7 110. Kg1 Be8 111. Qc3 Bf7 112. Qe5
|
||||
Bd5 113. Qc3 Be6 114. Qe5 Bd7 115. Qc3 Bf5 116. Qb3 Nh5 117. Qg8+ Ng7 118. Qb3
|
||||
Ne6 119. Kh2 Bf6 120. Kg1 Bg7 121. Kf1 Ng5 122. Qb6+ Bf6 123. Kg1 h3 124. gxh3
|
||||
Bxh3 125. Qd6 Bf5 126. Kg2 Nf3 127. Qd5 Kg5 128. Qg8+ Bg6 129. Qd5+ Be5 130.
|
||||
Qd8+ Kh5 131. Qd5 Bf5 132. Qf7+ Kg4 133. Qg8+ Ng5 134. Qc4 Bf4 135. Qg8 Be6 136.
|
||||
Qg7 Bf7 137. Qd4 Kf5 138. Qc5+ Be5 139. Qf8 Kg6 140. Qc5 Bf6 141. Qd6 Bc4 142.
|
||||
Qc6 Be6 143. Qd6 Bg4 144. Qd5 Bf3+ 145. Kf1 Nf7 146. Kg1 Ne5 147. Qg8+ Kf5 148.
|
||||
Qc8+ Kg5 149. Qg8+ Ng6 150. Qd5+ Kh6 151. Qe6 Be5 152. Qf5 Bf4 153. Qf6 Bg5 154.
|
||||
Qe6 Kg7 155. Qd7+ Ne7 156. Qe6 Bf6 157. Kf1 Kg6 158. Kg1 Nf5 159. Qg8+ Kh5 160.
|
||||
Qf7+ Kg5 161. Qg8+ Kf4 162. Qb8+ Kg4 163. Qg8+ Bg5 164. Qc8 Bf6 165. Qg8+ Kf4
|
||||
166. Qb8+ Be5 167. Qb4 Nd4 168. Qf8+ Kg5 169. Qg8+ Kh6 170. Qf8+ Bg7 171. Qd6+
|
||||
Kh5 172. Qh2+ Kg5 173. Qg3+ Bg4 174. Qe3+ Kf5 1/2-1/2
|
|
@ -0,0 +1,47 @@
|
|||
[Event "Grand Slam Final Masters"]
|
||||
[Site "Bilbao ESP"]
|
||||
[Date "2010.10.11"]
|
||||
[Round "3"]
|
||||
[White "Shirov, Alexei"]
|
||||
[Black "Carlsen, Magnus"]
|
||||
[Result "1/2-1/2"]
|
||||
[WhiteTitle "GM"]
|
||||
[BlackTitle "GM"]
|
||||
[WhiteElo "2749"]
|
||||
[BlackElo "2826"]
|
||||
[ECO "C95"]
|
||||
[Opening "Ruy Lopez"]
|
||||
[Variation "closed, Breyer, Borisenko variation"]
|
||||
[WhiteFideId "2209390"]
|
||||
[BlackFideId "1503014"]
|
||||
[EventDate "2010.10.09"]
|
||||
[EventType "DRR"]
|
||||
|
||||
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3
|
||||
O-O 9. h3 Nb8 10. d4 Nbd7 11. Nbd2 Bb7 12. Bc2 Re8 13. a4 Bf8 14. Bd3 c6 15. b4
|
||||
Nb6 16. axb5 cxb5 17. d5 Rc8 18. Bb2 Nh5 19. Bf1 f5 20. Nxe5 Rxe5 21. c4 Nf6 22.
|
||||
Bxe5 dxe5 23. c5 fxe4 24. d6 Na4 25. Nc4 Nxc5 26. bxc5 Rxc5 27. Qb3 Bd5 28. Qb4
|
||||
Rxc4 29. Bxc4 bxc4 30. Rxa6 Qc8 31. Qa5 c3 32. d7 Qxd7 33. Qxc3 Qb7 34. Rea1 Qb8
|
||||
35. Ra7 h6 36. Rc7 Qb6 37. Qxe5 Bd6 38. Rc8+ Kf7 39. Qc3 Qb7 40. Rca8 Qxa8 41.
|
||||
Rxa8 Bxa8 42. Qd4 Bd5 43. Qa7+ Be7 44. Qc7 h5 45. Qe5 g6 46. Kh2 Be6 47. Kg1 Bf5
|
||||
48. Kf1 Ne8 49. Kg1 Ng7 50. Qd5+ Ne6 51. Qb7 h4 52. Kh2 Nf4 53. Kg1 Nd3 54. Kf1
|
||||
Nc5 55. Qd5+ Be6 56. Qe5 Bf5 57. Qd5+ Ne6 58. Qb7 Kf8 59. Qa8+ Bd8 60. Qa7 Bf6
|
||||
61. Qb7 Kg8 62. Qa7 Bg5 63. Ke2 Nf4+ 64. Kf1 Nh5 65. Ke2 Kf8 66. Kf1 Bf6 67. Qc7
|
||||
Ng7 68. Qa7 Ne6 69. Qb7 Nd8 70. Qa7 Nf7 71. Kg1 Kg7 72. Kf1 Be5 73. Qe7 g5 74.
|
||||
Kg1 Bf6 75. Qb7 Kg6 76. Qd5 Ne5 77. Qg8+ Bg7 78. Qe8+ Kh6 79. Qe7 Nd3 80. Kf1
|
||||
Nf4 81. Qd6+ Bg6 82. Qe7 Nd5 83. Qe6 Nf6 84. Kg1 Be8 85. Qf5 Bd7 86. Qe5 Kg6 87.
|
||||
Kf1 Bf8 88. Kg1 Ba3 89. Qc7 Bb4 90. Qe5 Bd2 91. Qd4 Bf4 92. Qb6 Be8 93. Kf1 Bf7
|
||||
94. Kg1 Kf5 95. Qa7 Be6 96. Kf1 Kg6 97. Qb6 Bd7 98. Kg1 Ba4 99. Qe6 Bb5 100. Qb6
|
||||
Bc4 101. Qd4 Be6 102. Kf1 Bf5 103. Kg1 g4 104. hxg4 Bxg4 105. Qc3 Bf5 106. Qb3
|
||||
Bg5 107. Kf1 Kh6 108. Kg1 Kg6 109. Kf1 Bd7 110. Kg1 Be8 111. Qc3 Bf7 112. Qe5
|
||||
Bd5 113. Qc3 Be6 114. Qe5 Bd7 115. Qc3 Bf5 116. Qb3 Nh5 117. Qg8+ Ng7 118. Qb3
|
||||
Ne6 119. Kh2 Bf6 120. Kg1 Bg7 121. Kf1 Ng5 122. Qb6+ Bf6 123. Kg1 h3 124. gxh3
|
||||
Bxh3 125. Qd6 Bf5 126. Kg2 Nf3 127. Qd5 Kg5 128. Qg8+ Bg6 129. Qd5+ Be5 130.
|
||||
Qd8+ Kh5 131. Qd5 Bf5 132. Qf7+ Kg4 133. Qg8+ Ng5 134. Qc4 Bf4 135. Qg8 Be6 136.
|
||||
Qg7 Bf7 137. Qd4 Kf5 138. Qc5+ Be5 139. Qf8 Kg6 140. Qc5 Bf6 141. Qd6 Bc4 142.
|
||||
Qc6 Be6 143. Qd6 Bg4 144. Qd5 Bf3+ 145. Kf1 Nf7 146. Kg1 Ne5 147. Qg8+ Kf5 148.
|
||||
Qc8+ Kg5 149. Qg8+ Ng6 150. Qd5+ Kh6 151. Qe6 Be5 152. Qf5 Bf4 153. Qf6 Bg5 154.
|
||||
Qe6 Kg7 155. Qd7+ Ne7 156. Qe6 Bf6 157. Kf1 Kg6 158. Kg1 Nf5 159. Qg8+ Kh5 160.
|
||||
Qf7+ Kg5 161. Qg8+ Kf4 162. Qb8+ Kg4 163. Qg8+ Bg5 164. Qc8 Bf6 165. Qg8+ Kf4
|
||||
166. Qb8+ Be5 167. Qb4 Nd4 168. Qf8+ Kg5 169. Qg8+ Kh6 170. Qf8+ Bg7 171. Qd6+
|
||||
Kh5 172. Qh2+ Kg5 173. Qg3+ Bg4 174. Qe3+ Kf5 1/2-1/2
|
|
@ -0,0 +1,28 @@
|
|||
[Event "Grand Slam Final Masters"]
|
||||
[Site "Bilbao ESP"]
|
||||
[Date "2010.10.11"]
|
||||
[Round "3"]
|
||||
[White "Shirov, Alexei"]
|
||||
[Black "Carlsen, Magnus"]
|
||||
[Result "1/2-1/2"]
|
||||
[WhiteTitle "GM"]
|
||||
[BlackTitle "GM"]
|
||||
[WhiteElo "2749"]
|
||||
[BlackElo "2826"]
|
||||
[ECO "C95"]
|
||||
[Opening "Ruy Lopez"]
|
||||
[Variation "closed, Breyer, Borisenko variation"]
|
||||
[WhiteFideId "2209390"]
|
||||
[BlackFideId "1503014"]
|
||||
[EventDate "2010.10.09"]
|
||||
[EventType "DRR"]
|
||||
|
||||
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3
|
||||
O-O 9. h3 Nb8 10. d4 Nbd7 11. Nbd2 Bb7 12. Bc2 Re8 13. a4 Bf8 14. Bd3 c6 15. b4
|
||||
Nb6 16. axb5 cxb5 17. d5 Rc8 18. Bb2 Nh5 19. Bf1 f5 20. Nxe5 Rxe5 21. c4 Nf6 22.
|
||||
Bxe5 dxe5 23. c5 fxe4 24. d6 Na4 25. Nc4 Nxc5 26. bxc5 Rxc5 27. Qb3 Bd5 28. Qb4
|
||||
Rxc4 29. Bxc4 bxc4 30. Rxa6 Qc8 31. Qa5 c3 32. d7 Qxd7 33. Qxc3 Qb7 34. Rea1 Qb8
|
||||
35. Ra7 h6 36. Rc7 Qb6 37. Qxe5 Bd6 38. Rc8+ Kf7 39. Qc3 Qb7 40. Rca8 Qxa8 41.
|
||||
Rxa8 Bxa8 42. Qd4 Bd5 43. Qa7+ Be7 44. Qc7 h5 45. Qe5 g6 46. Kh2 Be6 47. Kg1 Bf5
|
||||
48. Kf1 Ne8 49. Kg1 Ng7 50. Qd5+ Ne6 51. Qb7 h4 52. Kh2 Nf4 53. Kg1 Nd3 54. Kf1
|
||||
Nc5 55. Qd5+ Be6 56. Qe5 Bf5 57. Qd5+ Ne6 58. Qb7 Kf8 59. Qa8+ Bd8 60. Qa7 Bf6
|
|
@ -0,0 +1,47 @@
|
|||
[Event "Grand Slam Final Masters"]
|
||||
[Site "Bilbao ESP"]
|
||||
[Date "2010.10.11"]
|
||||
[Round "3"]
|
||||
[White "Shirov, Alexei"]
|
||||
[Black "Carlsen, Magnus"]
|
||||
[Result "1/2-1/2"]
|
||||
[WhiteTitle "GM"]
|
||||
[BlackTitle "GM"]
|
||||
[WhiteElo "2749"]
|
||||
[BlackElo "2826"]
|
||||
[ECO "C95"]
|
||||
[Opening "Ruy Lopez"]
|
||||
[Variation "closed, Breyer, Borisenko variation"]
|
||||
[WhiteFideId "2209390"]
|
||||
[BlackFideId "1503014"]
|
||||
[EventDate "2010.10.09"]
|
||||
[EventType "DRR"]
|
||||
|
||||
1. e4 e5 2. Nf3 Nc8 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3
|
||||
O-O 9. h3 Nb8 10. d4 Nbd7 11. Nbd2 Bb7 12. Bc2 Re8 13. a4 Bf8 14. Bd3 c6 15. b4
|
||||
Nb6 16. axb5 cxb5 17. d5 Rc8 18. Bb2 Nh5 19. Bf1 f5 20. Nxe5 Rxe5 21. c4 Nf6 22.
|
||||
Bxe5 dxe5 23. c5 fxe4 24. d6 Na4 25. Nc4 Nxc5 26. bxc5 Rxc5 27. Qb3 Bd5 28. Qb4
|
||||
Rxc4 29. Bxc4 bxc4 30. Rxa6 Qc8 31. Qa5 c3 32. d7 Qxd7 33. Qxc3 Qb7 34. Rea1 Qb8
|
||||
35. Ra7 h6 36. Rc7 Qb6 37. Qxe5 Bd6 38. Rc8+ Kf7 39. Qc3 Qb7 40. Rca8 Qxa8 41.
|
||||
Rxa8 Bxa8 42. Qd4 Bd5 43. Qa7+ Be7 44. Qc7 h5 45. Qe5 g6 46. Kh2 Be6 47. Kg1 Bf5
|
||||
48. Kf1 Ne8 49. Kg1 Ng7 50. Qd5+ Ne6 51. Qb7 h4 52. Kh2 Nf4 53. Kg1 Nd3 54. Kf1
|
||||
Nc5 55. Qd5+ Be6 56. Qe5 Bf5 57. Qd5+ Ne6 58. Qb7 Kf8 59. Qa8+ Bd8 60. Qa7 Bf6
|
||||
61. Qb7 Kg8 62. Qa7 Bg5 63. Ke2 Nf4+ 64. Kf1 Nh5 65. Ke2 Kf8 66. Kf1 Bf6 67. Qc7
|
||||
Ng7 68. Qa7 Ne6 69. Qb7 Nd8 70. Qa7 Nf7 71. Kg1 Kg7 72. Kf1 Be5 73. Qe7 g5 74.
|
||||
Kg1 Bf6 75. Qb7 Kg6 76. Qd5 Ne5 77. Qg8+ Bg7 78. Qe8+ Kh6 79. Qe7 Nd3 80. Kf1
|
||||
Nf4 81. Qd6+ Bg6 82. Qe7 Nd5 83. Qe6 Nf6 84. Kg1 Be8 85. Qf5 Bd7 86. Qe5 Kg6 87.
|
||||
Kf1 Bf8 88. Kg1 Ba3 89. Qc7 Bb4 90. Qe5 Bd2 91. Qd4 Bf4 92. Qb6 Be8 93. Kf1 Bf7
|
||||
94. Kg1 Kf5 95. Qa7 Be6 96. Kf1 Kg6 97. Qb6 Bd7 98. Kg1 Ba4 99. Qe6 Bb5 100. Qb6
|
||||
Bc4 101. Qd4 Be6 102. Kf1 Bf5 103. Kg1 g4 104. hxg4 Bxg4 105. Qc3 Bf5 106. Qb3
|
||||
Bg5 107. Kf1 Kh6 108. Kg1 Kg6 109. Kf1 Bd7 110. Kg1 Be8 111. Qc3 Bf7 112. Qe5
|
||||
Bd5 113. Qc3 Be6 114. Qe5 Bd7 115. Qc3 Bf5 116. Qb3 Nh5 117. Qg8+ Ng7 118. Qb3
|
||||
Ne6 119. Kh2 Bf6 120. Kg1 Bg7 121. Kf1 Ng5 122. Qb6+ Bf6 123. Kg1 h3 124. gxh3
|
||||
Bxh3 125. Qd6 Bf5 126. Kg2 Nf3 127. Qd5 Kg5 128. Qg8+ Bg6 129. Qd5+ Be5 130.
|
||||
Qd8+ Kh5 131. Qd5 Bf5 132. Qf7+ Kg4 133. Qg8+ Ng5 134. Qc4 Bf4 135. Qg8 Be6 136.
|
||||
Qg7 Bf7 137. Qd4 Kf5 138. Qc5+ Be5 139. Qf8 Kg6 140. Qc5 Bf6 141. Qd6 Bc4 142.
|
||||
Qc6 Be6 143. Qd6 Bg4 144. Qd5 Bf3+ 145. Kf1 Nf7 146. Kg1 Ne5 147. Qg8+ Kf5 148.
|
||||
Qc8+ Kg5 149. Qg8+ Ng6 150. Qd5+ Kh6 151. Qe6 Be5 152. Qf5 Bf4 153. Qf6 Bg5 154.
|
||||
Qe6 Kg7 155. Qd7+ Ne7 156. Qe6 Bf6 157. Kf1 Kg6 158. Kg1 Nf5 159. Qg8+ Kh5 160.
|
||||
Qf7+ Kg5 161. Qg8+ Kf4 162. Qb8+ Kg4 163. Qg8+ Bg5 164. Qc8 Bf6 165. Qg8+ Kf4
|
||||
166. Qb8+ Be5 167. Qb4 Nd4 168. Qf8+ Kg5 169. Qg8+ Kh6 170. Qf8+ Bg7 171. Qd6+
|
||||
Kh5 172. Qh2+ Kg5 173. Qg3+ Bg4 174. Qe3+ Kf5 1/2-1/2
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,190 @@
|
|||
# TODO: Fix typing in this file.
|
||||
# mypy: ignore-errors
|
||||
|
||||
import chess.svg
|
||||
|
||||
|
||||
class WidgetError(Exception):
|
||||
"""
|
||||
raised when ipywidgets is not installed
|
||||
"""
|
||||
|
||||
|
||||
class NotJupyter(Exception):
|
||||
"""
|
||||
raised when InteractiveViewer is instantiated from a non jupyter shell
|
||||
"""
|
||||
|
||||
|
||||
try:
|
||||
from ipywidgets import Button, GridBox, Layout, HTML, Output, HBox, Select
|
||||
from IPython.display import display, clear_output
|
||||
except ModuleNotFoundError:
|
||||
raise WidgetError("You need to have ipywidgets installed and running from Jupyter")
|
||||
|
||||
|
||||
class InteractiveViewer:
|
||||
def __new__(cls, game):
|
||||
jupyter = True
|
||||
try:
|
||||
if get_ipython().__class__.__name__ != "ZMQInteractiveShell":
|
||||
jupyter = False
|
||||
except NameError:
|
||||
jupyter = False
|
||||
|
||||
if not jupyter:
|
||||
raise NotJupyter("The interactive viewer only runs in Jupyter shell")
|
||||
|
||||
return object.__new__(cls)
|
||||
|
||||
def __init__(self, game):
|
||||
self.game = game
|
||||
self.__board = game.board()
|
||||
self.__moves = list(game.mainline_moves())
|
||||
self.__white_moves = [str(move) for (i, move) in enumerate(self.__moves) if i % 2 == 0]
|
||||
self.__black_moves = [str(move) for (i, move) in enumerate(self.__moves) if i % 2 == 1]
|
||||
self.__move_list_len = len(self.__white_moves)
|
||||
self.__num_moves = len(self.__moves)
|
||||
self.__next_move = 0 if self.__moves else None
|
||||
self.__out = Output()
|
||||
|
||||
def __next_click(self, _):
|
||||
move = self.__moves[self.__next_move]
|
||||
self.__next_move += 1
|
||||
self.__board.push(move)
|
||||
self.show()
|
||||
|
||||
def __prev_click(self, _):
|
||||
self.__board.pop()
|
||||
self.__next_move -= 1
|
||||
self.show()
|
||||
|
||||
def __reset_click(self, _):
|
||||
self.__board.reset()
|
||||
self.__next_move = 0
|
||||
self.show()
|
||||
|
||||
def __white_select_change(self, change):
|
||||
new = change["new"]
|
||||
if (isinstance(new, dict)) and ("index" in new):
|
||||
target = new["index"] * 2
|
||||
self.__seek(target)
|
||||
self.show()
|
||||
|
||||
def __black_select_change(self, change):
|
||||
new = change["new"]
|
||||
if (isinstance(new, dict)) and ("index" in new):
|
||||
target = new["index"] * 2 + 1
|
||||
self.__seek(target)
|
||||
self.show()
|
||||
|
||||
def __seek(self, target):
|
||||
while self.__next_move <= target:
|
||||
move = self.__moves[self.__next_move]
|
||||
self.__next_move += 1
|
||||
self.__board.push(move)
|
||||
|
||||
while self.__next_move > target + 1:
|
||||
self.__board.pop()
|
||||
self.__next_move -= 1
|
||||
|
||||
def show(self):
|
||||
display(self.__out)
|
||||
next_move = Button(
|
||||
icon="step-forward",
|
||||
layout=Layout(width="60px", grid_area="right"),
|
||||
disabled=self.__next_move >= self.__num_moves,
|
||||
)
|
||||
|
||||
prev_move = Button(
|
||||
icon="step-backward",
|
||||
layout=Layout(width="60px", grid_area="left"),
|
||||
disabled=self.__next_move == 0,
|
||||
)
|
||||
|
||||
reset = Button(
|
||||
icon="stop",
|
||||
layout=Layout(width="60px", grid_area="middle"),
|
||||
disabled=self.__next_move == 0,
|
||||
)
|
||||
|
||||
if self.__next_move == 0:
|
||||
white_move = None
|
||||
black_move = None
|
||||
else:
|
||||
white_move = (
|
||||
self.__white_moves[self.__next_move // 2]
|
||||
if (self.__next_move % 2) == 1
|
||||
else None
|
||||
)
|
||||
black_move = (
|
||||
self.__black_moves[self.__next_move // 2 - 1]
|
||||
if (self.__next_move % 2) == 0
|
||||
else None
|
||||
)
|
||||
|
||||
white_move_list = Select(
|
||||
options=self.__white_moves,
|
||||
value=white_move,
|
||||
rows=max(self.__move_list_len, 24),
|
||||
disabled=False,
|
||||
layout=Layout(width="80px"),
|
||||
)
|
||||
|
||||
black_move_list = Select(
|
||||
options=self.__black_moves,
|
||||
value=black_move,
|
||||
rows=max(self.__move_list_len, 24),
|
||||
disabled=False,
|
||||
layout=Layout(width="80px"),
|
||||
)
|
||||
|
||||
white_move_list.observe(self.__white_select_change)
|
||||
black_move_list.observe(self.__black_select_change)
|
||||
|
||||
move_number_width = 3 + len(str(self.__move_list_len)) * 10
|
||||
|
||||
move_number = Select(
|
||||
options=range(1, self.__move_list_len + 1),
|
||||
value=None,
|
||||
disabled=True,
|
||||
rows=max(self.__move_list_len, 24),
|
||||
layout=Layout(width=f"{move_number_width}px"),
|
||||
)
|
||||
|
||||
move_list = HBox(
|
||||
[move_number, white_move_list, black_move_list],
|
||||
layout=Layout(height="407px", grid_area="moves"),
|
||||
)
|
||||
|
||||
next_move.on_click(self.__next_click)
|
||||
prev_move.on_click(self.__prev_click)
|
||||
reset.on_click(self.__reset_click)
|
||||
|
||||
with self.__out:
|
||||
grid_box = GridBox(
|
||||
children=[next_move, prev_move, reset, self.svg, move_list],
|
||||
layout=Layout(
|
||||
width=f"{390+move_number_width+160}px",
|
||||
grid_template_rows="90% 10%",
|
||||
grid_template_areas="""
|
||||
"top top top top top moves"
|
||||
". left middle right . moves"
|
||||
""",
|
||||
),
|
||||
)
|
||||
clear_output(wait=True)
|
||||
display(grid_box)
|
||||
|
||||
@property
|
||||
def svg(self) -> HTML:
|
||||
svg = chess.svg.board(
|
||||
board=self.__board,
|
||||
size=390,
|
||||
lastmove=self.__board.peek() if self.__board.move_stack else None,
|
||||
check=self.__board.king(self.__board.turn)
|
||||
if self.__board.is_check()
|
||||
else None,
|
||||
)
|
||||
svg_widget = HTML(value=svg, layout=Layout(grid_area="top"))
|
||||
return svg_widget
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,542 @@
|
|||
# This file is part of the python-chess library.
|
||||
# Copyright (C) 2012-2021 Niklas Fiekas <niklas.fiekas@backscattering.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import chess
|
||||
import struct
|
||||
import os
|
||||
import mmap
|
||||
import random
|
||||
import typing
|
||||
|
||||
from types import TracebackType
|
||||
from typing import Callable, Container, Iterator, List, NamedTuple, Optional, Type, Union
|
||||
|
||||
|
||||
PathLike = Union[str, bytes, os.PathLike]
|
||||
|
||||
|
||||
ENTRY_STRUCT = struct.Struct(">QHHI")
|
||||
|
||||
|
||||
POLYGLOT_RANDOM_ARRAY = [
|
||||
0x9D39247E33776D41, 0x2AF7398005AAA5C7, 0x44DB015024623547, 0x9C15F73E62A76AE2,
|
||||
0x75834465489C0C89, 0x3290AC3A203001BF, 0x0FBBAD1F61042279, 0xE83A908FF2FB60CA,
|
||||
0x0D7E765D58755C10, 0x1A083822CEAFE02D, 0x9605D5F0E25EC3B0, 0xD021FF5CD13A2ED5,
|
||||
0x40BDF15D4A672E32, 0x011355146FD56395, 0x5DB4832046F3D9E5, 0x239F8B2D7FF719CC,
|
||||
0x05D1A1AE85B49AA1, 0x679F848F6E8FC971, 0x7449BBFF801FED0B, 0x7D11CDB1C3B7ADF0,
|
||||
0x82C7709E781EB7CC, 0xF3218F1C9510786C, 0x331478F3AF51BBE6, 0x4BB38DE5E7219443,
|
||||
0xAA649C6EBCFD50FC, 0x8DBD98A352AFD40B, 0x87D2074B81D79217, 0x19F3C751D3E92AE1,
|
||||
0xB4AB30F062B19ABF, 0x7B0500AC42047AC4, 0xC9452CA81A09D85D, 0x24AA6C514DA27500,
|
||||
0x4C9F34427501B447, 0x14A68FD73C910841, 0xA71B9B83461CBD93, 0x03488B95B0F1850F,
|
||||
0x637B2B34FF93C040, 0x09D1BC9A3DD90A94, 0x3575668334A1DD3B, 0x735E2B97A4C45A23,
|
||||
0x18727070F1BD400B, 0x1FCBACD259BF02E7, 0xD310A7C2CE9B6555, 0xBF983FE0FE5D8244,
|
||||
0x9F74D14F7454A824, 0x51EBDC4AB9BA3035, 0x5C82C505DB9AB0FA, 0xFCF7FE8A3430B241,
|
||||
0x3253A729B9BA3DDE, 0x8C74C368081B3075, 0xB9BC6C87167C33E7, 0x7EF48F2B83024E20,
|
||||
0x11D505D4C351BD7F, 0x6568FCA92C76A243, 0x4DE0B0F40F32A7B8, 0x96D693460CC37E5D,
|
||||
0x42E240CB63689F2F, 0x6D2BDCDAE2919661, 0x42880B0236E4D951, 0x5F0F4A5898171BB6,
|
||||
0x39F890F579F92F88, 0x93C5B5F47356388B, 0x63DC359D8D231B78, 0xEC16CA8AEA98AD76,
|
||||
0x5355F900C2A82DC7, 0x07FB9F855A997142, 0x5093417AA8A7ED5E, 0x7BCBC38DA25A7F3C,
|
||||
0x19FC8A768CF4B6D4, 0x637A7780DECFC0D9, 0x8249A47AEE0E41F7, 0x79AD695501E7D1E8,
|
||||
0x14ACBAF4777D5776, 0xF145B6BECCDEA195, 0xDABF2AC8201752FC, 0x24C3C94DF9C8D3F6,
|
||||
0xBB6E2924F03912EA, 0x0CE26C0B95C980D9, 0xA49CD132BFBF7CC4, 0xE99D662AF4243939,
|
||||
0x27E6AD7891165C3F, 0x8535F040B9744FF1, 0x54B3F4FA5F40D873, 0x72B12C32127FED2B,
|
||||
0xEE954D3C7B411F47, 0x9A85AC909A24EAA1, 0x70AC4CD9F04F21F5, 0xF9B89D3E99A075C2,
|
||||
0x87B3E2B2B5C907B1, 0xA366E5B8C54F48B8, 0xAE4A9346CC3F7CF2, 0x1920C04D47267BBD,
|
||||
0x87BF02C6B49E2AE9, 0x092237AC237F3859, 0xFF07F64EF8ED14D0, 0x8DE8DCA9F03CC54E,
|
||||
0x9C1633264DB49C89, 0xB3F22C3D0B0B38ED, 0x390E5FB44D01144B, 0x5BFEA5B4712768E9,
|
||||
0x1E1032911FA78984, 0x9A74ACB964E78CB3, 0x4F80F7A035DAFB04, 0x6304D09A0B3738C4,
|
||||
0x2171E64683023A08, 0x5B9B63EB9CEFF80C, 0x506AACF489889342, 0x1881AFC9A3A701D6,
|
||||
0x6503080440750644, 0xDFD395339CDBF4A7, 0xEF927DBCF00C20F2, 0x7B32F7D1E03680EC,
|
||||
0xB9FD7620E7316243, 0x05A7E8A57DB91B77, 0xB5889C6E15630A75, 0x4A750A09CE9573F7,
|
||||
0xCF464CEC899A2F8A, 0xF538639CE705B824, 0x3C79A0FF5580EF7F, 0xEDE6C87F8477609D,
|
||||
0x799E81F05BC93F31, 0x86536B8CF3428A8C, 0x97D7374C60087B73, 0xA246637CFF328532,
|
||||
0x043FCAE60CC0EBA0, 0x920E449535DD359E, 0x70EB093B15B290CC, 0x73A1921916591CBD,
|
||||
0x56436C9FE1A1AA8D, 0xEFAC4B70633B8F81, 0xBB215798D45DF7AF, 0x45F20042F24F1768,
|
||||
0x930F80F4E8EB7462, 0xFF6712FFCFD75EA1, 0xAE623FD67468AA70, 0xDD2C5BC84BC8D8FC,
|
||||
0x7EED120D54CF2DD9, 0x22FE545401165F1C, 0xC91800E98FB99929, 0x808BD68E6AC10365,
|
||||
0xDEC468145B7605F6, 0x1BEDE3A3AEF53302, 0x43539603D6C55602, 0xAA969B5C691CCB7A,
|
||||
0xA87832D392EFEE56, 0x65942C7B3C7E11AE, 0xDED2D633CAD004F6, 0x21F08570F420E565,
|
||||
0xB415938D7DA94E3C, 0x91B859E59ECB6350, 0x10CFF333E0ED804A, 0x28AED140BE0BB7DD,
|
||||
0xC5CC1D89724FA456, 0x5648F680F11A2741, 0x2D255069F0B7DAB3, 0x9BC5A38EF729ABD4,
|
||||
0xEF2F054308F6A2BC, 0xAF2042F5CC5C2858, 0x480412BAB7F5BE2A, 0xAEF3AF4A563DFE43,
|
||||
0x19AFE59AE451497F, 0x52593803DFF1E840, 0xF4F076E65F2CE6F0, 0x11379625747D5AF3,
|
||||
0xBCE5D2248682C115, 0x9DA4243DE836994F, 0x066F70B33FE09017, 0x4DC4DE189B671A1C,
|
||||
0x51039AB7712457C3, 0xC07A3F80C31FB4B4, 0xB46EE9C5E64A6E7C, 0xB3819A42ABE61C87,
|
||||
0x21A007933A522A20, 0x2DF16F761598AA4F, 0x763C4A1371B368FD, 0xF793C46702E086A0,
|
||||
0xD7288E012AEB8D31, 0xDE336A2A4BC1C44B, 0x0BF692B38D079F23, 0x2C604A7A177326B3,
|
||||
0x4850E73E03EB6064, 0xCFC447F1E53C8E1B, 0xB05CA3F564268D99, 0x9AE182C8BC9474E8,
|
||||
0xA4FC4BD4FC5558CA, 0xE755178D58FC4E76, 0x69B97DB1A4C03DFE, 0xF9B5B7C4ACC67C96,
|
||||
0xFC6A82D64B8655FB, 0x9C684CB6C4D24417, 0x8EC97D2917456ED0, 0x6703DF9D2924E97E,
|
||||
0xC547F57E42A7444E, 0x78E37644E7CAD29E, 0xFE9A44E9362F05FA, 0x08BD35CC38336615,
|
||||
0x9315E5EB3A129ACE, 0x94061B871E04DF75, 0xDF1D9F9D784BA010, 0x3BBA57B68871B59D,
|
||||
0xD2B7ADEEDED1F73F, 0xF7A255D83BC373F8, 0xD7F4F2448C0CEB81, 0xD95BE88CD210FFA7,
|
||||
0x336F52F8FF4728E7, 0xA74049DAC312AC71, 0xA2F61BB6E437FDB5, 0x4F2A5CB07F6A35B3,
|
||||
0x87D380BDA5BF7859, 0x16B9F7E06C453A21, 0x7BA2484C8A0FD54E, 0xF3A678CAD9A2E38C,
|
||||
0x39B0BF7DDE437BA2, 0xFCAF55C1BF8A4424, 0x18FCF680573FA594, 0x4C0563B89F495AC3,
|
||||
0x40E087931A00930D, 0x8CFFA9412EB642C1, 0x68CA39053261169F, 0x7A1EE967D27579E2,
|
||||
0x9D1D60E5076F5B6F, 0x3810E399B6F65BA2, 0x32095B6D4AB5F9B1, 0x35CAB62109DD038A,
|
||||
0xA90B24499FCFAFB1, 0x77A225A07CC2C6BD, 0x513E5E634C70E331, 0x4361C0CA3F692F12,
|
||||
0xD941ACA44B20A45B, 0x528F7C8602C5807B, 0x52AB92BEB9613989, 0x9D1DFA2EFC557F73,
|
||||
0x722FF175F572C348, 0x1D1260A51107FE97, 0x7A249A57EC0C9BA2, 0x04208FE9E8F7F2D6,
|
||||
0x5A110C6058B920A0, 0x0CD9A497658A5698, 0x56FD23C8F9715A4C, 0x284C847B9D887AAE,
|
||||
0x04FEABFBBDB619CB, 0x742E1E651C60BA83, 0x9A9632E65904AD3C, 0x881B82A13B51B9E2,
|
||||
0x506E6744CD974924, 0xB0183DB56FFC6A79, 0x0ED9B915C66ED37E, 0x5E11E86D5873D484,
|
||||
0xF678647E3519AC6E, 0x1B85D488D0F20CC5, 0xDAB9FE6525D89021, 0x0D151D86ADB73615,
|
||||
0xA865A54EDCC0F019, 0x93C42566AEF98FFB, 0x99E7AFEABE000731, 0x48CBFF086DDF285A,
|
||||
0x7F9B6AF1EBF78BAF, 0x58627E1A149BBA21, 0x2CD16E2ABD791E33, 0xD363EFF5F0977996,
|
||||
0x0CE2A38C344A6EED, 0x1A804AADB9CFA741, 0x907F30421D78C5DE, 0x501F65EDB3034D07,
|
||||
0x37624AE5A48FA6E9, 0x957BAF61700CFF4E, 0x3A6C27934E31188A, 0xD49503536ABCA345,
|
||||
0x088E049589C432E0, 0xF943AEE7FEBF21B8, 0x6C3B8E3E336139D3, 0x364F6FFA464EE52E,
|
||||
0xD60F6DCEDC314222, 0x56963B0DCA418FC0, 0x16F50EDF91E513AF, 0xEF1955914B609F93,
|
||||
0x565601C0364E3228, 0xECB53939887E8175, 0xBAC7A9A18531294B, 0xB344C470397BBA52,
|
||||
0x65D34954DAF3CEBD, 0xB4B81B3FA97511E2, 0xB422061193D6F6A7, 0x071582401C38434D,
|
||||
0x7A13F18BBEDC4FF5, 0xBC4097B116C524D2, 0x59B97885E2F2EA28, 0x99170A5DC3115544,
|
||||
0x6F423357E7C6A9F9, 0x325928EE6E6F8794, 0xD0E4366228B03343, 0x565C31F7DE89EA27,
|
||||
0x30F5611484119414, 0xD873DB391292ED4F, 0x7BD94E1D8E17DEBC, 0xC7D9F16864A76E94,
|
||||
0x947AE053EE56E63C, 0xC8C93882F9475F5F, 0x3A9BF55BA91F81CA, 0xD9A11FBB3D9808E4,
|
||||
0x0FD22063EDC29FCA, 0xB3F256D8ACA0B0B9, 0xB03031A8B4516E84, 0x35DD37D5871448AF,
|
||||
0xE9F6082B05542E4E, 0xEBFAFA33D7254B59, 0x9255ABB50D532280, 0xB9AB4CE57F2D34F3,
|
||||
0x693501D628297551, 0xC62C58F97DD949BF, 0xCD454F8F19C5126A, 0xBBE83F4ECC2BDECB,
|
||||
0xDC842B7E2819E230, 0xBA89142E007503B8, 0xA3BC941D0A5061CB, 0xE9F6760E32CD8021,
|
||||
0x09C7E552BC76492F, 0x852F54934DA55CC9, 0x8107FCCF064FCF56, 0x098954D51FFF6580,
|
||||
0x23B70EDB1955C4BF, 0xC330DE426430F69D, 0x4715ED43E8A45C0A, 0xA8D7E4DAB780A08D,
|
||||
0x0572B974F03CE0BB, 0xB57D2E985E1419C7, 0xE8D9ECBE2CF3D73F, 0x2FE4B17170E59750,
|
||||
0x11317BA87905E790, 0x7FBF21EC8A1F45EC, 0x1725CABFCB045B00, 0x964E915CD5E2B207,
|
||||
0x3E2B8BCBF016D66D, 0xBE7444E39328A0AC, 0xF85B2B4FBCDE44B7, 0x49353FEA39BA63B1,
|
||||
0x1DD01AAFCD53486A, 0x1FCA8A92FD719F85, 0xFC7C95D827357AFA, 0x18A6A990C8B35EBD,
|
||||
0xCCCB7005C6B9C28D, 0x3BDBB92C43B17F26, 0xAA70B5B4F89695A2, 0xE94C39A54A98307F,
|
||||
0xB7A0B174CFF6F36E, 0xD4DBA84729AF48AD, 0x2E18BC1AD9704A68, 0x2DE0966DAF2F8B1C,
|
||||
0xB9C11D5B1E43A07E, 0x64972D68DEE33360, 0x94628D38D0C20584, 0xDBC0D2B6AB90A559,
|
||||
0xD2733C4335C6A72F, 0x7E75D99D94A70F4D, 0x6CED1983376FA72B, 0x97FCAACBF030BC24,
|
||||
0x7B77497B32503B12, 0x8547EDDFB81CCB94, 0x79999CDFF70902CB, 0xCFFE1939438E9B24,
|
||||
0x829626E3892D95D7, 0x92FAE24291F2B3F1, 0x63E22C147B9C3403, 0xC678B6D860284A1C,
|
||||
0x5873888850659AE7, 0x0981DCD296A8736D, 0x9F65789A6509A440, 0x9FF38FED72E9052F,
|
||||
0xE479EE5B9930578C, 0xE7F28ECD2D49EECD, 0x56C074A581EA17FE, 0x5544F7D774B14AEF,
|
||||
0x7B3F0195FC6F290F, 0x12153635B2C0CF57, 0x7F5126DBBA5E0CA7, 0x7A76956C3EAFB413,
|
||||
0x3D5774A11D31AB39, 0x8A1B083821F40CB4, 0x7B4A38E32537DF62, 0x950113646D1D6E03,
|
||||
0x4DA8979A0041E8A9, 0x3BC36E078F7515D7, 0x5D0A12F27AD310D1, 0x7F9D1A2E1EBE1327,
|
||||
0xDA3A361B1C5157B1, 0xDCDD7D20903D0C25, 0x36833336D068F707, 0xCE68341F79893389,
|
||||
0xAB9090168DD05F34, 0x43954B3252DC25E5, 0xB438C2B67F98E5E9, 0x10DCD78E3851A492,
|
||||
0xDBC27AB5447822BF, 0x9B3CDB65F82CA382, 0xB67B7896167B4C84, 0xBFCED1B0048EAC50,
|
||||
0xA9119B60369FFEBD, 0x1FFF7AC80904BF45, 0xAC12FB171817EEE7, 0xAF08DA9177DDA93D,
|
||||
0x1B0CAB936E65C744, 0xB559EB1D04E5E932, 0xC37B45B3F8D6F2BA, 0xC3A9DC228CAAC9E9,
|
||||
0xF3B8B6675A6507FF, 0x9FC477DE4ED681DA, 0x67378D8ECCEF96CB, 0x6DD856D94D259236,
|
||||
0xA319CE15B0B4DB31, 0x073973751F12DD5E, 0x8A8E849EB32781A5, 0xE1925C71285279F5,
|
||||
0x74C04BF1790C0EFE, 0x4DDA48153C94938A, 0x9D266D6A1CC0542C, 0x7440FB816508C4FE,
|
||||
0x13328503DF48229F, 0xD6BF7BAEE43CAC40, 0x4838D65F6EF6748F, 0x1E152328F3318DEA,
|
||||
0x8F8419A348F296BF, 0x72C8834A5957B511, 0xD7A023A73260B45C, 0x94EBC8ABCFB56DAE,
|
||||
0x9FC10D0F989993E0, 0xDE68A2355B93CAE6, 0xA44CFE79AE538BBE, 0x9D1D84FCCE371425,
|
||||
0x51D2B1AB2DDFB636, 0x2FD7E4B9E72CD38C, 0x65CA5B96B7552210, 0xDD69A0D8AB3B546D,
|
||||
0x604D51B25FBF70E2, 0x73AA8A564FB7AC9E, 0x1A8C1E992B941148, 0xAAC40A2703D9BEA0,
|
||||
0x764DBEAE7FA4F3A6, 0x1E99B96E70A9BE8B, 0x2C5E9DEB57EF4743, 0x3A938FEE32D29981,
|
||||
0x26E6DB8FFDF5ADFE, 0x469356C504EC9F9D, 0xC8763C5B08D1908C, 0x3F6C6AF859D80055,
|
||||
0x7F7CC39420A3A545, 0x9BFB227EBDF4C5CE, 0x89039D79D6FC5C5C, 0x8FE88B57305E2AB6,
|
||||
0xA09E8C8C35AB96DE, 0xFA7E393983325753, 0xD6B6D0ECC617C699, 0xDFEA21EA9E7557E3,
|
||||
0xB67C1FA481680AF8, 0xCA1E3785A9E724E5, 0x1CFC8BED0D681639, 0xD18D8549D140CAEA,
|
||||
0x4ED0FE7E9DC91335, 0xE4DBF0634473F5D2, 0x1761F93A44D5AEFE, 0x53898E4C3910DA55,
|
||||
0x734DE8181F6EC39A, 0x2680B122BAA28D97, 0x298AF231C85BAFAB, 0x7983EED3740847D5,
|
||||
0x66C1A2A1A60CD889, 0x9E17E49642A3E4C1, 0xEDB454E7BADC0805, 0x50B704CAB602C329,
|
||||
0x4CC317FB9CDDD023, 0x66B4835D9EAFEA22, 0x219B97E26FFC81BD, 0x261E4E4C0A333A9D,
|
||||
0x1FE2CCA76517DB90, 0xD7504DFA8816EDBB, 0xB9571FA04DC089C8, 0x1DDC0325259B27DE,
|
||||
0xCF3F4688801EB9AA, 0xF4F5D05C10CAB243, 0x38B6525C21A42B0E, 0x36F60E2BA4FA6800,
|
||||
0xEB3593803173E0CE, 0x9C4CD6257C5A3603, 0xAF0C317D32ADAA8A, 0x258E5A80C7204C4B,
|
||||
0x8B889D624D44885D, 0xF4D14597E660F855, 0xD4347F66EC8941C3, 0xE699ED85B0DFB40D,
|
||||
0x2472F6207C2D0484, 0xC2A1E7B5B459AEB5, 0xAB4F6451CC1D45EC, 0x63767572AE3D6174,
|
||||
0xA59E0BD101731A28, 0x116D0016CB948F09, 0x2CF9C8CA052F6E9F, 0x0B090A7560A968E3,
|
||||
0xABEEDDB2DDE06FF1, 0x58EFC10B06A2068D, 0xC6E57A78FBD986E0, 0x2EAB8CA63CE802D7,
|
||||
0x14A195640116F336, 0x7C0828DD624EC390, 0xD74BBE77E6116AC7, 0x804456AF10F5FB53,
|
||||
0xEBE9EA2ADF4321C7, 0x03219A39EE587A30, 0x49787FEF17AF9924, 0xA1E9300CD8520548,
|
||||
0x5B45E522E4B1B4EF, 0xB49C3B3995091A36, 0xD4490AD526F14431, 0x12A8F216AF9418C2,
|
||||
0x001F837CC7350524, 0x1877B51E57A764D5, 0xA2853B80F17F58EE, 0x993E1DE72D36D310,
|
||||
0xB3598080CE64A656, 0x252F59CF0D9F04BB, 0xD23C8E176D113600, 0x1BDA0492E7E4586E,
|
||||
0x21E0BD5026C619BF, 0x3B097ADAF088F94E, 0x8D14DEDB30BE846E, 0xF95CFFA23AF5F6F4,
|
||||
0x3871700761B3F743, 0xCA672B91E9E4FA16, 0x64C8E531BFF53B55, 0x241260ED4AD1E87D,
|
||||
0x106C09B972D2E822, 0x7FBA195410E5CA30, 0x7884D9BC6CB569D8, 0x0647DFEDCD894A29,
|
||||
0x63573FF03E224774, 0x4FC8E9560F91B123, 0x1DB956E450275779, 0xB8D91274B9E9D4FB,
|
||||
0xA2EBEE47E2FBFCE1, 0xD9F1F30CCD97FB09, 0xEFED53D75FD64E6B, 0x2E6D02C36017F67F,
|
||||
0xA9AA4D20DB084E9B, 0xB64BE8D8B25396C1, 0x70CB6AF7C2D5BCF0, 0x98F076A4F7A2322E,
|
||||
0xBF84470805E69B5F, 0x94C3251F06F90CF3, 0x3E003E616A6591E9, 0xB925A6CD0421AFF3,
|
||||
0x61BDD1307C66E300, 0xBF8D5108E27E0D48, 0x240AB57A8B888B20, 0xFC87614BAF287E07,
|
||||
0xEF02CDD06FFDB432, 0xA1082C0466DF6C0A, 0x8215E577001332C8, 0xD39BB9C3A48DB6CF,
|
||||
0x2738259634305C14, 0x61CF4F94C97DF93D, 0x1B6BACA2AE4E125B, 0x758F450C88572E0B,
|
||||
0x959F587D507A8359, 0xB063E962E045F54D, 0x60E8ED72C0DFF5D1, 0x7B64978555326F9F,
|
||||
0xFD080D236DA814BA, 0x8C90FD9B083F4558, 0x106F72FE81E2C590, 0x7976033A39F7D952,
|
||||
0xA4EC0132764CA04B, 0x733EA705FAE4FA77, 0xB4D8F77BC3E56167, 0x9E21F4F903B33FD9,
|
||||
0x9D765E419FB69F6D, 0xD30C088BA61EA5EF, 0x5D94337FBFAF7F5B, 0x1A4E4822EB4D7A59,
|
||||
0x6FFE73E81B637FB3, 0xDDF957BC36D8B9CA, 0x64D0E29EEA8838B3, 0x08DD9BDFD96B9F63,
|
||||
0x087E79E5A57D1D13, 0xE328E230E3E2B3FB, 0x1C2559E30F0946BE, 0x720BF5F26F4D2EAA,
|
||||
0xB0774D261CC609DB, 0x443F64EC5A371195, 0x4112CF68649A260E, 0xD813F2FAB7F5C5CA,
|
||||
0x660D3257380841EE, 0x59AC2C7873F910A3, 0xE846963877671A17, 0x93B633ABFA3469F8,
|
||||
0xC0C0F5A60EF4CDCF, 0xCAF21ECD4377B28C, 0x57277707199B8175, 0x506C11B9D90E8B1D,
|
||||
0xD83CC2687A19255F, 0x4A29C6465A314CD1, 0xED2DF21216235097, 0xB5635C95FF7296E2,
|
||||
0x22AF003AB672E811, 0x52E762596BF68235, 0x9AEBA33AC6ECC6B0, 0x944F6DE09134DFB6,
|
||||
0x6C47BEC883A7DE39, 0x6AD047C430A12104, 0xA5B1CFDBA0AB4067, 0x7C45D833AFF07862,
|
||||
0x5092EF950A16DA0B, 0x9338E69C052B8E7B, 0x455A4B4CFE30E3F5, 0x6B02E63195AD0CF8,
|
||||
0x6B17B224BAD6BF27, 0xD1E0CCD25BB9C169, 0xDE0C89A556B9AE70, 0x50065E535A213CF6,
|
||||
0x9C1169FA2777B874, 0x78EDEFD694AF1EED, 0x6DC93D9526A50E68, 0xEE97F453F06791ED,
|
||||
0x32AB0EDB696703D3, 0x3A6853C7E70757A7, 0x31865CED6120F37D, 0x67FEF95D92607890,
|
||||
0x1F2B1D1F15F6DC9C, 0xB69E38A8965C6B65, 0xAA9119FF184CCCF4, 0xF43C732873F24C13,
|
||||
0xFB4A3D794A9A80D2, 0x3550C2321FD6109C, 0x371F77E76BB8417E, 0x6BFA9AAE5EC05779,
|
||||
0xCD04F3FF001A4778, 0xE3273522064480CA, 0x9F91508BFFCFC14A, 0x049A7F41061A9E60,
|
||||
0xFCB6BE43A9F2FE9B, 0x08DE8A1C7797DA9B, 0x8F9887E6078735A1, 0xB5B4071DBFC73A66,
|
||||
0x230E343DFBA08D33, 0x43ED7F5A0FAE657D, 0x3A88A0FBBCB05C63, 0x21874B8B4D2DBC4F,
|
||||
0x1BDEA12E35F6A8C9, 0x53C065C6C8E63528, 0xE34A1D250E7A8D6B, 0xD6B04D3B7651DD7E,
|
||||
0x5E90277E7CB39E2D, 0x2C046F22062DC67D, 0xB10BB459132D0A26, 0x3FA9DDFB67E2F199,
|
||||
0x0E09B88E1914F7AF, 0x10E8B35AF3EEAB37, 0x9EEDECA8E272B933, 0xD4C718BC4AE8AE5F,
|
||||
0x81536D601170FC20, 0x91B534F885818A06, 0xEC8177F83F900978, 0x190E714FADA5156E,
|
||||
0xB592BF39B0364963, 0x89C350C893AE7DC1, 0xAC042E70F8B383F2, 0xB49B52E587A1EE60,
|
||||
0xFB152FE3FF26DA89, 0x3E666E6F69AE2C15, 0x3B544EBE544C19F9, 0xE805A1E290CF2456,
|
||||
0x24B33C9D7ED25117, 0xE74733427B72F0C1, 0x0A804D18B7097475, 0x57E3306D881EDB4F,
|
||||
0x4AE7D6A36EB5DBCB, 0x2D8D5432157064C8, 0xD1E649DE1E7F268B, 0x8A328A1CEDFE552C,
|
||||
0x07A3AEC79624C7DA, 0x84547DDC3E203C94, 0x990A98FD5071D263, 0x1A4FF12616EEFC89,
|
||||
0xF6F7FD1431714200, 0x30C05B1BA332F41C, 0x8D2636B81555A786, 0x46C9FEB55D120902,
|
||||
0xCCEC0A73B49C9921, 0x4E9D2827355FC492, 0x19EBB029435DCB0F, 0x4659D2B743848A2C,
|
||||
0x963EF2C96B33BE31, 0x74F85198B05A2E7D, 0x5A0F544DD2B1FB18, 0x03727073C2E134B1,
|
||||
0xC7F6AA2DE59AEA61, 0x352787BAA0D7C22F, 0x9853EAB63B5E0B35, 0xABBDCDD7ED5C0860,
|
||||
0xCF05DAF5AC8D77B0, 0x49CAD48CEBF4A71E, 0x7A4C10EC2158C4A6, 0xD9E92AA246BF719E,
|
||||
0x13AE978D09FE5557, 0x730499AF921549FF, 0x4E4B705B92903BA4, 0xFF577222C14F0A3A,
|
||||
0x55B6344CF97AAFAE, 0xB862225B055B6960, 0xCAC09AFBDDD2CDB4, 0xDAF8E9829FE96B5F,
|
||||
0xB5FDFC5D3132C498, 0x310CB380DB6F7503, 0xE87FBB46217A360E, 0x2102AE466EBB1148,
|
||||
0xF8549E1A3AA5E00D, 0x07A69AFDCC42261A, 0xC4C118BFE78FEAAE, 0xF9F4892ED96BD438,
|
||||
0x1AF3DBE25D8F45DA, 0xF5B4B0B0D2DEEEB4, 0x962ACEEFA82E1C84, 0x046E3ECAAF453CE9,
|
||||
0xF05D129681949A4C, 0x964781CE734B3C84, 0x9C2ED44081CE5FBD, 0x522E23F3925E319E,
|
||||
0x177E00F9FC32F791, 0x2BC60A63A6F3B3F2, 0x222BBFAE61725606, 0x486289DDCC3D6780,
|
||||
0x7DC7785B8EFDFC80, 0x8AF38731C02BA980, 0x1FAB64EA29A2DDF7, 0xE4D9429322CD065A,
|
||||
0x9DA058C67844F20C, 0x24C0E332B70019B0, 0x233003B5A6CFE6AD, 0xD586BD01C5C217F6,
|
||||
0x5E5637885F29BC2B, 0x7EBA726D8C94094B, 0x0A56A5F0BFE39272, 0xD79476A84EE20D06,
|
||||
0x9E4C1269BAA4BF37, 0x17EFEE45B0DEE640, 0x1D95B0A5FCF90BC6, 0x93CBE0B699C2585D,
|
||||
0x65FA4F227A2B6D79, 0xD5F9E858292504D5, 0xC2B5A03F71471A6F, 0x59300222B4561E00,
|
||||
0xCE2F8642CA0712DC, 0x7CA9723FBB2E8988, 0x2785338347F2BA08, 0xC61BB3A141E50E8C,
|
||||
0x150F361DAB9DEC26, 0x9F6A419D382595F4, 0x64A53DC924FE7AC9, 0x142DE49FFF7A7C3D,
|
||||
0x0C335248857FA9E7, 0x0A9C32D5EAE45305, 0xE6C42178C4BBB92E, 0x71F1CE2490D20B07,
|
||||
0xF1BCC3D275AFE51A, 0xE728E8C83C334074, 0x96FBF83A12884624, 0x81A1549FD6573DA5,
|
||||
0x5FA7867CAF35E149, 0x56986E2EF3ED091B, 0x917F1DD5F8886C61, 0xD20D8C88C8FFE65F,
|
||||
0x31D71DCE64B2C310, 0xF165B587DF898190, 0xA57E6339DD2CF3A0, 0x1EF6E6DBB1961EC9,
|
||||
0x70CC73D90BC26E24, 0xE21A6B35DF0C3AD7, 0x003A93D8B2806962, 0x1C99DED33CB890A1,
|
||||
0xCF3145DE0ADD4289, 0xD0E4427A5514FB72, 0x77C621CC9FB3A483, 0x67A34DAC4356550B,
|
||||
0xF8D626AAAF278509
|
||||
]
|
||||
|
||||
|
||||
class ZobristHasher:
|
||||
def __init__(self, array: List[int]) -> None:
|
||||
assert len(array) >= 781
|
||||
self.array = array
|
||||
|
||||
def hash_board(self, board: chess.BaseBoard) -> int:
|
||||
zobrist_hash = 0
|
||||
|
||||
for pivot, squares in enumerate(board.occupied_co):
|
||||
for square in chess.scan_reversed(squares):
|
||||
piece_index = (typing.cast(chess.PieceType, board.piece_type_at(square)) - 1) * 2 + pivot
|
||||
zobrist_hash ^= self.array[64 * piece_index + square]
|
||||
|
||||
return zobrist_hash
|
||||
|
||||
def hash_castling(self, board: chess.Board) -> int:
|
||||
zobrist_hash = 0
|
||||
|
||||
# Hash in the castling flags.
|
||||
if board.has_kingside_castling_rights(chess.WHITE):
|
||||
zobrist_hash ^= self.array[768]
|
||||
if board.has_queenside_castling_rights(chess.WHITE):
|
||||
zobrist_hash ^= self.array[768 + 1]
|
||||
if board.has_kingside_castling_rights(chess.BLACK):
|
||||
zobrist_hash ^= self.array[768 + 2]
|
||||
if board.has_queenside_castling_rights(chess.BLACK):
|
||||
zobrist_hash ^= self.array[768 + 3]
|
||||
|
||||
return zobrist_hash
|
||||
|
||||
def hash_ep_square(self, board: chess.Board) -> int:
|
||||
# Hash in the en passant file.
|
||||
if board.ep_square:
|
||||
# But only if there's actually a pawn ready to capture it. Legality
|
||||
# of the potential capture is irrelevant.
|
||||
if board.turn == chess.WHITE:
|
||||
ep_mask = chess.shift_down(chess.BB_SQUARES[board.ep_square])
|
||||
else:
|
||||
ep_mask = chess.shift_up(chess.BB_SQUARES[board.ep_square])
|
||||
ep_mask = chess.shift_left(ep_mask) | chess.shift_right(ep_mask)
|
||||
|
||||
if ep_mask & board.pawns & board.occupied_co[board.turn]:
|
||||
return self.array[772 + chess.square_file(board.ep_square)]
|
||||
return 0
|
||||
|
||||
def hash_turn(self, board: chess.Board) -> int:
|
||||
# Hash in the turn.
|
||||
return self.array[780] if board.turn == chess.WHITE else 0
|
||||
|
||||
def __call__(self, board: chess.Board) -> int:
|
||||
return (self.hash_board(board) ^ self.hash_castling(board) ^
|
||||
self.hash_ep_square(board) ^ self.hash_turn(board))
|
||||
|
||||
|
||||
def zobrist_hash(board: chess.Board, *, _hasher: Callable[[chess.Board], int] = ZobristHasher(POLYGLOT_RANDOM_ARRAY)) -> int:
|
||||
"""
|
||||
Calculates the Polyglot Zobrist hash of the position.
|
||||
|
||||
A Zobrist hash is an XOR of pseudo-random values picked from
|
||||
an array. Which values are picked is decided by features of the
|
||||
position, such as piece positions, castling rights and en passant
|
||||
squares.
|
||||
"""
|
||||
return _hasher(board)
|
||||
|
||||
|
||||
class Entry(NamedTuple):
|
||||
"""An entry from a Polyglot opening book."""
|
||||
|
||||
key: int
|
||||
"""The Zobrist hash of the position."""
|
||||
|
||||
raw_move: int
|
||||
"""
|
||||
The raw binary representation of the move. Use
|
||||
:data:`~chess.polyglot.Entry.move` instead.
|
||||
"""
|
||||
|
||||
weight: int
|
||||
"""An integer value that can be used as the weight for this entry."""
|
||||
|
||||
learn: int
|
||||
"""Another integer value that can be used for extra information."""
|
||||
|
||||
move: chess.Move
|
||||
"""The :class:`~chess.Move`."""
|
||||
|
||||
|
||||
class _EmptyMmap(bytearray):
|
||||
def size(self) -> int:
|
||||
return 0
|
||||
|
||||
def close(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def _randint(rng: Optional[random.Random], a: int, b: int) -> int:
|
||||
return random.randint(a, b) if rng is None else rng.randint(a, b)
|
||||
|
||||
|
||||
class MemoryMappedReader:
|
||||
"""Maps a Polyglot opening book to memory."""
|
||||
|
||||
def __init__(self, filename: PathLike) -> None:
|
||||
self.fd = os.open(filename, os.O_RDONLY | os.O_BINARY if hasattr(os, "O_BINARY") else os.O_RDONLY)
|
||||
|
||||
try:
|
||||
self.mmap: Union[mmap.mmap, _EmptyMmap] = mmap.mmap(self.fd, 0, access=mmap.ACCESS_READ)
|
||||
except (ValueError, OSError):
|
||||
self.mmap = _EmptyMmap() # Workaround for empty opening books.
|
||||
|
||||
if self.mmap.size() % ENTRY_STRUCT.size != 0:
|
||||
raise IOError(f"invalid file size: ensure {filename!r} is a valid polyglot opening book")
|
||||
|
||||
try:
|
||||
# Python 3.8
|
||||
self.mmap.madvise(mmap.MADV_RANDOM) # type: ignore
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def __enter__(self) -> MemoryMappedReader:
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType]) -> None:
|
||||
return self.close()
|
||||
|
||||
def __len__(self) -> int:
|
||||
return self.mmap.size() // ENTRY_STRUCT.size
|
||||
|
||||
def __getitem__(self, index: int) -> Entry:
|
||||
if index < 0:
|
||||
index = len(self) + index
|
||||
|
||||
try:
|
||||
key, raw_move, weight, learn = ENTRY_STRUCT.unpack_from(self.mmap, index * ENTRY_STRUCT.size)
|
||||
except struct.error:
|
||||
raise IndexError()
|
||||
|
||||
# Extract source and target square.
|
||||
to_square = raw_move & 0x3f
|
||||
from_square = (raw_move >> 6) & 0x3f
|
||||
|
||||
# Extract the promotion type.
|
||||
promotion_part = (raw_move >> 12) & 0x7
|
||||
promotion = promotion_part + 1 if promotion_part else None
|
||||
|
||||
# Piece drop.
|
||||
if from_square == to_square:
|
||||
promotion, drop = None, promotion
|
||||
else:
|
||||
drop = None
|
||||
|
||||
# Entry with move (not normalized).
|
||||
move = chess.Move(from_square, to_square, promotion, drop)
|
||||
return Entry(key, raw_move, weight, learn, move)
|
||||
|
||||
def __iter__(self) -> Iterator[Entry]:
|
||||
i = 0
|
||||
size = len(self)
|
||||
while i < size:
|
||||
yield self[i]
|
||||
i += 1
|
||||
|
||||
def bisect_key_left(self, key: int) -> int:
|
||||
lo = 0
|
||||
hi = len(self)
|
||||
|
||||
while lo < hi:
|
||||
mid = (lo + hi) // 2
|
||||
mid_key, _, _, _ = ENTRY_STRUCT.unpack_from(self.mmap, mid * ENTRY_STRUCT.size)
|
||||
if mid_key < key:
|
||||
lo = mid + 1
|
||||
else:
|
||||
hi = mid
|
||||
|
||||
return lo
|
||||
|
||||
def __contains__(self, entry: Entry) -> bool:
|
||||
return any(current == entry for current in self.find_all(entry.key, minimum_weight=entry.weight))
|
||||
|
||||
def find_all(self, board: Union[chess.Board, int], *, minimum_weight: int = 1, exclude_moves: Container[chess.Move] = []) -> Iterator[Entry]:
|
||||
"""Seeks a specific position and yields corresponding entries."""
|
||||
try:
|
||||
key = int(board) # type: ignore
|
||||
context: Optional[chess.Board] = None
|
||||
except (TypeError, ValueError):
|
||||
context = typing.cast(chess.Board, board)
|
||||
key = zobrist_hash(context)
|
||||
|
||||
i = self.bisect_key_left(key)
|
||||
size = len(self)
|
||||
|
||||
while i < size:
|
||||
entry = self[i]
|
||||
i += 1
|
||||
|
||||
if entry.key != key:
|
||||
break
|
||||
|
||||
if entry.weight < minimum_weight:
|
||||
continue
|
||||
|
||||
if context:
|
||||
move = context._from_chess960(context.chess960, entry.move.from_square, entry.move.to_square, entry.move.promotion, entry.move.drop)
|
||||
entry = Entry(entry.key, entry.raw_move, entry.weight, entry.learn, move)
|
||||
|
||||
if exclude_moves and entry.move in exclude_moves:
|
||||
continue
|
||||
|
||||
if context and not context.is_legal(entry.move):
|
||||
continue
|
||||
|
||||
yield entry
|
||||
|
||||
def find(self, board: Union[chess.Board, int], *, minimum_weight: int = 1, exclude_moves: Container[chess.Move] = []) -> Entry:
|
||||
"""
|
||||
Finds the main entry for the given position or Zobrist hash.
|
||||
|
||||
The main entry is the (first) entry with the highest weight.
|
||||
|
||||
By default, entries with weight ``0`` are excluded. This is a common
|
||||
way to delete entries from an opening book without compacting it. Pass
|
||||
*minimum_weight* ``0`` to select all entries.
|
||||
|
||||
:raises: :exc:`IndexError` if no entries are found. Use
|
||||
:func:`~chess.polyglot.MemoryMappedReader.get()` if you prefer to
|
||||
get ``None`` instead of an exception.
|
||||
"""
|
||||
try:
|
||||
return max(self.find_all(board, minimum_weight=minimum_weight, exclude_moves=exclude_moves), key=lambda entry: entry.weight)
|
||||
except ValueError:
|
||||
raise IndexError()
|
||||
|
||||
def get(self, board: Union[chess.Board, int], default: Optional[Entry] = None, *, minimum_weight: int = 1, exclude_moves: Container[chess.Move] = []) -> Optional[Entry]:
|
||||
try:
|
||||
return self.find(board, minimum_weight=minimum_weight, exclude_moves=exclude_moves)
|
||||
except IndexError:
|
||||
return default
|
||||
|
||||
def choice(self, board: Union[chess.Board, int], *, minimum_weight: int = 1, exclude_moves: Container[chess.Move] = [], random: Optional[random.Random] = None) -> Entry:
|
||||
"""
|
||||
Uniformly selects a random entry for the given position.
|
||||
|
||||
:raises: :exc:`IndexError` if no entries are found.
|
||||
"""
|
||||
chosen_entry = None
|
||||
|
||||
for i, entry in enumerate(self.find_all(board, minimum_weight=minimum_weight, exclude_moves=exclude_moves)):
|
||||
if chosen_entry is None or _randint(random, 0, i) == i:
|
||||
chosen_entry = entry
|
||||
|
||||
if chosen_entry is None:
|
||||
raise IndexError()
|
||||
|
||||
return chosen_entry
|
||||
|
||||
def weighted_choice(self, board: Union[chess.Board, int], *, exclude_moves: Container[chess.Move] = [], random: Optional[random.Random] = None) -> Entry:
|
||||
"""
|
||||
Selects a random entry for the given position, distributed by the
|
||||
weights of the entries.
|
||||
|
||||
:raises: :exc:`IndexError` if no entries are found.
|
||||
"""
|
||||
total_weights = sum(entry.weight for entry in self.find_all(board, exclude_moves=exclude_moves))
|
||||
if not total_weights:
|
||||
raise IndexError()
|
||||
|
||||
choice = _randint(random, 0, total_weights - 1)
|
||||
|
||||
current_sum = 0
|
||||
for entry in self.find_all(board, exclude_moves=exclude_moves):
|
||||
current_sum += entry.weight
|
||||
if current_sum > choice:
|
||||
return entry
|
||||
|
||||
assert False
|
||||
|
||||
def close(self) -> None:
|
||||
"""Closes the reader."""
|
||||
self.mmap.close()
|
||||
|
||||
try:
|
||||
os.close(self.fd)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def open_reader(path: PathLike) -> MemoryMappedReader:
|
||||
"""
|
||||
Creates a reader for the file at the given path.
|
||||
|
||||
The following example opens a book to find all entries for the start
|
||||
position:
|
||||
|
||||
>>> import chess
|
||||
>>> import chess.polyglot
|
||||
>>>
|
||||
>>> board = chess.Board()
|
||||
>>>
|
||||
>>> with chess.polyglot.open_reader("data/polyglot/performance.bin") as reader:
|
||||
... for entry in reader.find_all(board):
|
||||
... print(entry.move, entry.weight, entry.learn)
|
||||
e2e4 1 0
|
||||
d2d4 1 0
|
||||
c2c4 1 0
|
||||
"""
|
||||
return MemoryMappedReader(path)
|
|
@ -0,0 +1,466 @@
|
|||
# This file is part of the python-chess library.
|
||||
# Copyright (C) 2016-2021 Niklas Fiekas <niklas.fiekas@backscattering.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Piece vector graphics are copyright (C) Colin M.L. Burnett
|
||||
# <https://en.wikipedia.org/wiki/User:Cburnett> and also licensed under the
|
||||
# GNU General Public License.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import chess
|
||||
|
||||
from typing import Dict, Iterable, Optional, Tuple, Union
|
||||
from chess import Color, IntoSquareSet, Square
|
||||
|
||||
|
||||
SQUARE_SIZE = 45
|
||||
MARGIN = 20
|
||||
|
||||
PIECES = {
|
||||
"b": """<g id="black-bishop" class="black bishop" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 36c3.39-.97 10.11.43 13.5-2 3.39 2.43 10.11 1.03 13.5 2 0 0 1.65.54 3 2-.68.97-1.65.99-3 .5-3.39-.97-10.11.46-13.5-1-3.39 1.46-10.11.03-13.5 1-1.354.49-2.323.47-3-.5 1.354-1.94 3-2 3-2zm6-4c2.5 2.5 12.5 2.5 15 0 .5-1.5 0-2 0-2 0-2.5-2.5-4-2.5-4 5.5-1.5 6-11.5-5-15.5-11 4-10.5 14-5 15.5 0 0-2.5 1.5-2.5 4 0 0-.5.5 0 2zM25 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 1 1 5 0z" fill="#000" stroke-linecap="butt"/><path d="M17.5 26h10M15 30h15m-7.5-14.5v5M20 18h5" stroke="#fff" stroke-linejoin="miter"/></g>""", # noqa: E501
|
||||
"k": """<g id="black-king" class="black king" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22.5 11.63V6" stroke-linejoin="miter"/><path d="M22.5 25s4.5-7.5 3-10.5c0 0-1-2.5-3-2.5s-3 2.5-3 2.5c-1.5 3 3 10.5 3 10.5" fill="#000" stroke-linecap="butt" stroke-linejoin="miter"/><path d="M11.5 37c5.5 3.5 15.5 3.5 21 0v-7s9-4.5 6-10.5c-4-6.5-13.5-3.5-16 4V27v-3.5c-3.5-7.5-13-10.5-16-4-3 6 5 10 5 10V37z" fill="#000"/><path d="M20 8h5" stroke-linejoin="miter"/><path d="M32 29.5s8.5-4 6.03-9.65C34.15 14 25 18 22.5 24.5l.01 2.1-.01-2.1C20 18 9.906 14 6.997 19.85c-2.497 5.65 4.853 9 4.853 9M11.5 30c5.5-3 15.5-3 21 0m-21 3.5c5.5-3 15.5-3 21 0m-21 3.5c5.5-3 15.5-3 21 0" stroke="#fff"/></g>""", # noqa: E501
|
||||
"n": """<g id="black-knight" class="black knight" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18" style="fill:#000000; stroke:#000000;"/><path d="M 24,18 C 24.38,20.91 18.45,25.37 16,27 C 13,29 13.18,31.34 11,31 C 9.958,30.06 12.41,27.96 11,28 C 10,28 11.19,29.23 10,30 C 9,30 5.997,31 6,26 C 6,24 12,14 12,14 C 12,14 13.89,12.1 14,10.5 C 13.27,9.506 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.28,8.008 21,7 C 22,7 22,10 22,10" style="fill:#000000; stroke:#000000;"/><path d="M 9.5 25.5 A 0.5 0.5 0 1 1 8.5,25.5 A 0.5 0.5 0 1 1 9.5 25.5 z" style="fill:#ececec; stroke:#ececec;"/><path d="M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z" transform="matrix(0.866,0.5,-0.5,0.866,9.693,-5.173)" style="fill:#ececec; stroke:#ececec;"/><path d="M 24.55,10.4 L 24.1,11.85 L 24.6,12 C 27.75,13 30.25,14.49 32.5,18.75 C 34.75,23.01 35.75,29.06 35.25,39 L 35.2,39.5 L 37.45,39.5 L 37.5,39 C 38,28.94 36.62,22.15 34.25,17.66 C 31.88,13.17 28.46,11.02 25.06,10.5 L 24.55,10.4 z " style="fill:#ececec; stroke:none;"/></g>""", # noqa: E501
|
||||
"p": """<g id="black-pawn" class="black pawn"><path d="M22.5 9c-2.21 0-4 1.79-4 4 0 .89.29 1.71.78 2.38C17.33 16.5 16 18.59 16 21c0 2.03.94 3.84 2.41 5.03-3 1.06-7.41 5.55-7.41 13.47h23c0-7.92-4.41-12.41-7.41-13.47 1.47-1.19 2.41-3 2.41-5.03 0-2.41-1.33-4.5-3.28-5.62.49-.67.78-1.49.78-2.38 0-2.21-1.79-4-4-4z" stroke="#000" stroke-width="1.5" stroke-linecap="round"/></g>""", # noqa: E501
|
||||
"q": """<g id="black-queen" class="black queen" fill="#000" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><g fill="#000" stroke="none"><circle cx="6" cy="12" r="2.75"/><circle cx="14" cy="9" r="2.75"/><circle cx="22.5" cy="8" r="2.75"/><circle cx="31" cy="9" r="2.75"/><circle cx="39" cy="12" r="2.75"/></g><path d="M9 26c8.5-1.5 21-1.5 27 0l2.5-12.5L31 25l-.3-14.1-5.2 13.6-3-14.5-3 14.5-5.2-13.6L14 25 6.5 13.5 9 26zM9 26c0 2 1.5 2 2.5 4 1 1.5 1 1 .5 3.5-1.5 1-1.5 2.5-1.5 2.5-1.5 1.5.5 2.5.5 2.5 6.5 1 16.5 1 23 0 0 0 1.5-1 0-2.5 0 0 .5-1.5-1-2.5-.5-2.5-.5-2 .5-3.5 1-2 2.5-2 2.5-4-8.5-1.5-18.5-1.5-27 0z" stroke-linecap="butt"/><path d="M11 38.5a35 35 1 0 0 23 0" fill="none" stroke-linecap="butt"/><path d="M11 29a35 35 1 0 1 23 0M12.5 31.5h20M11.5 34.5a35 35 1 0 0 22 0M10.5 37.5a35 35 1 0 0 24 0" fill="none" stroke="#fff"/></g>""", # noqa: E501
|
||||
"r": """<g id="black-rook" class="black rook" fill="#000" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 39h27v-3H9v3zM12.5 32l1.5-2.5h17l1.5 2.5h-20zM12 36v-4h21v4H12z" stroke-linecap="butt"/><path d="M14 29.5v-13h17v13H14z" stroke-linecap="butt" stroke-linejoin="miter"/><path d="M14 16.5L11 14h23l-3 2.5H14zM11 14V9h4v2h5V9h5v2h5V9h4v5H11z" stroke-linecap="butt"/><path d="M12 35.5h21M13 31.5h19M14 29.5h17M14 16.5h17M11 14h23" fill="none" stroke="#fff" stroke-width="1" stroke-linejoin="miter"/></g>""", # noqa: E501
|
||||
"B": """<g id="white-bishop" class="white bishop" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><g fill="#fff" stroke-linecap="butt"><path d="M9 36c3.39-.97 10.11.43 13.5-2 3.39 2.43 10.11 1.03 13.5 2 0 0 1.65.54 3 2-.68.97-1.65.99-3 .5-3.39-.97-10.11.46-13.5-1-3.39 1.46-10.11.03-13.5 1-1.354.49-2.323.47-3-.5 1.354-1.94 3-2 3-2zM15 32c2.5 2.5 12.5 2.5 15 0 .5-1.5 0-2 0-2 0-2.5-2.5-4-2.5-4 5.5-1.5 6-11.5-5-15.5-11 4-10.5 14-5 15.5 0 0-2.5 1.5-2.5 4 0 0-.5.5 0 2zM25 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 1 1 5 0z"/></g><path d="M17.5 26h10M15 30h15m-7.5-14.5v5M20 18h5" stroke-linejoin="miter"/></g>""", # noqa: E501
|
||||
"K": """<g id="white-king" class="white king" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22.5 11.63V6M20 8h5" stroke-linejoin="miter"/><path d="M22.5 25s4.5-7.5 3-10.5c0 0-1-2.5-3-2.5s-3 2.5-3 2.5c-1.5 3 3 10.5 3 10.5" fill="#fff" stroke-linecap="butt" stroke-linejoin="miter"/><path d="M11.5 37c5.5 3.5 15.5 3.5 21 0v-7s9-4.5 6-10.5c-4-6.5-13.5-3.5-16 4V27v-3.5c-3.5-7.5-13-10.5-16-4-3 6 5 10 5 10V37z" fill="#fff"/><path d="M11.5 30c5.5-3 15.5-3 21 0m-21 3.5c5.5-3 15.5-3 21 0m-21 3.5c5.5-3 15.5-3 21 0"/></g>""", # noqa: E501
|
||||
"N": """<g id="white-knight" class="white knight" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18" style="fill:#ffffff; stroke:#000000;"/><path d="M 24,18 C 24.38,20.91 18.45,25.37 16,27 C 13,29 13.18,31.34 11,31 C 9.958,30.06 12.41,27.96 11,28 C 10,28 11.19,29.23 10,30 C 9,30 5.997,31 6,26 C 6,24 12,14 12,14 C 12,14 13.89,12.1 14,10.5 C 13.27,9.506 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.28,8.008 21,7 C 22,7 22,10 22,10" style="fill:#ffffff; stroke:#000000;"/><path d="M 9.5 25.5 A 0.5 0.5 0 1 1 8.5,25.5 A 0.5 0.5 0 1 1 9.5 25.5 z" style="fill:#000000; stroke:#000000;"/><path d="M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z" transform="matrix(0.866,0.5,-0.5,0.866,9.693,-5.173)" style="fill:#000000; stroke:#000000;"/></g>""", # noqa: E501
|
||||
"P": """<g id="white-pawn" class="white pawn"><path d="M22.5 9c-2.21 0-4 1.79-4 4 0 .89.29 1.71.78 2.38C17.33 16.5 16 18.59 16 21c0 2.03.94 3.84 2.41 5.03-3 1.06-7.41 5.55-7.41 13.47h23c0-7.92-4.41-12.41-7.41-13.47 1.47-1.19 2.41-3 2.41-5.03 0-2.41-1.33-4.5-3.28-5.62.49-.67.78-1.49.78-2.38 0-2.21-1.79-4-4-4z" fill="#fff" stroke="#000" stroke-width="1.5" stroke-linecap="round"/></g>""", # noqa: E501
|
||||
"Q": """<g id="white-queen" class="white queen" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 12a2 2 0 1 1-4 0 2 2 0 1 1 4 0zM24.5 7.5a2 2 0 1 1-4 0 2 2 0 1 1 4 0zM41 12a2 2 0 1 1-4 0 2 2 0 1 1 4 0zM16 8.5a2 2 0 1 1-4 0 2 2 0 1 1 4 0zM33 9a2 2 0 1 1-4 0 2 2 0 1 1 4 0z"/><path d="M9 26c8.5-1.5 21-1.5 27 0l2-12-7 11V11l-5.5 13.5-3-15-3 15-5.5-14V25L7 14l2 12zM9 26c0 2 1.5 2 2.5 4 1 1.5 1 1 .5 3.5-1.5 1-1.5 2.5-1.5 2.5-1.5 1.5.5 2.5.5 2.5 6.5 1 16.5 1 23 0 0 0 1.5-1 0-2.5 0 0 .5-1.5-1-2.5-.5-2.5-.5-2 .5-3.5 1-2 2.5-2 2.5-4-8.5-1.5-18.5-1.5-27 0z" stroke-linecap="butt"/><path d="M11.5 30c3.5-1 18.5-1 22 0M12 33.5c6-1 15-1 21 0" fill="none"/></g>""", # noqa: E501
|
||||
"R": """<g id="white-rook" class="white rook" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 39h27v-3H9v3zM12 36v-4h21v4H12zM11 14V9h4v2h5V9h5v2h5V9h4v5" stroke-linecap="butt"/><path d="M34 14l-3 3H14l-3-3"/><path d="M31 17v12.5H14V17" stroke-linecap="butt" stroke-linejoin="miter"/><path d="M31 29.5l1.5 2.5h-20l1.5-2.5"/><path d="M11 14h23" fill="none" stroke-linejoin="miter"/></g>""", # noqa: E501
|
||||
}
|
||||
|
||||
COORDS = {
|
||||
"1": """<path d="M6.754 26.996h2.578v-8.898l-2.805.562v-1.437l2.79-.563h1.578v10.336h2.578v1.328h-6.72z"/>""", # noqa: E501
|
||||
"2": """<path d="M8.195 26.996h5.508v1.328H6.297v-1.328q.898-.93 2.445-2.492 1.555-1.57 1.953-2.024.758-.851 1.055-1.437.305-.594.305-1.164 0-.93-.657-1.516-.648-.586-1.695-.586-.742 0-1.57.258-.82.258-1.758.781v-1.593q.953-.383 1.781-.578.828-.196 1.516-.196 1.812 0 2.89.906 1.079.907 1.079 2.422 0 .72-.274 1.368-.265.64-.976 1.515-.196.227-1.243 1.313-1.046 1.078-2.953 3.023z"/>""", # noqa: E501
|
||||
"3": """<path d="M11.434 22.035q1.132.242 1.765 1.008.64.766.64 1.89 0 1.727-1.187 2.672-1.187.946-3.375.946-.734 0-1.515-.149-.774-.14-1.602-.43V26.45q.656.383 1.438.578.78.196 1.632.196 1.485 0 2.258-.586.782-.586.782-1.703 0-1.032-.727-1.61-.719-.586-2.008-.586h-1.36v-1.297h1.423q1.164 0 1.78-.46.618-.47.618-1.344 0-.899-.64-1.375-.633-.485-1.82-.485-.65 0-1.391.141-.743.14-1.633.437V16.95q.898-.25 1.68-.375.788-.125 1.484-.125 1.797 0 2.844.82 1.046.813 1.046 2.204 0 .968-.554 1.64-.555.664-1.578.922z"/>""", # noqa: E501
|
||||
"4": """<path d="M11.016 18.035L7.03 24.262h3.985zm-.414-1.375h1.984v7.602h1.664v1.312h-1.664v2.75h-1.57v-2.75H5.75v-1.523z"/>""", # noqa: E501
|
||||
"5": """<path d="M6.719 16.66h6.195v1.328h-4.75v2.86q.344-.118.688-.172.343-.063.687-.063 1.953 0 3.094 1.07 1.14 1.07 1.14 2.899 0 1.883-1.171 2.93-1.172 1.039-3.305 1.039-.735 0-1.5-.125-.758-.125-1.57-.375v-1.586q.703.383 1.453.57.75.188 1.586.188 1.351 0 2.14-.711.79-.711.79-1.93 0-1.219-.79-1.93-.789-.71-2.14-.71-.633 0-1.266.14-.625.14-1.281.438z"/>""", # noqa: E501
|
||||
"6": """<path d="M10.137 21.863q-1.063 0-1.688.727-.617.726-.617 1.992 0 1.258.617 1.992.625.727 1.688.727 1.062 0 1.68-.727.624-.734.624-1.992 0-1.266-.625-1.992-.617-.727-1.68-.727zm3.133-4.945v1.437q-.594-.28-1.204-.43-.601-.148-1.195-.148-1.562 0-2.39 1.055-.82 1.055-.938 3.188.46-.68 1.156-1.04.696-.367 1.531-.367 1.758 0 2.774 1.07 1.023 1.063 1.023 2.899 0 1.797-1.062 2.883-1.063 1.086-2.828 1.086-2.024 0-3.094-1.547-1.07-1.555-1.07-4.5 0-2.766 1.312-4.406 1.313-1.649 3.524-1.649.593 0 1.195.117.61.118 1.266.352z"/>""", # noqa: E501
|
||||
"7": """<path d="M6.25 16.66h7.5v.672L9.516 28.324H7.867l3.985-10.336H6.25z"/>""", # noqa: E501
|
||||
"8": """<path d="M10 22.785q-1.125 0-1.773.602-.641.601-.641 1.656t.64 1.656q.649.602 1.774.602t1.773-.602q.649-.61.649-1.656 0-1.055-.649-1.656-.64-.602-1.773-.602zm-1.578-.672q-1.016-.25-1.586-.945-.563-.695-.563-1.695 0-1.399.993-2.211 1-.813 2.734-.813 1.742 0 2.734.813.993.812.993 2.21 0 1-.57 1.696-.563.695-1.571.945 1.14.266 1.773 1.04.641.773.641 1.89 0 1.695-1.04 2.602-1.03.906-2.96.906t-2.969-.906Q6 26.738 6 25.043q0-1.117.64-1.89.641-.774 1.782-1.04zm-.578-2.492q0 .906.562 1.414.57.508 1.594.508 1.016 0 1.586-.508.578-.508.578-1.414 0-.906-.578-1.414-.57-.508-1.586-.508-1.023 0-1.594.508-.562.508-.562 1.414z"/>""", # noqa: E501
|
||||
"a": """<path d="M23.328 10.016q-1.742 0-2.414.398-.672.398-.672 1.36 0 .765.5 1.218.508.445 1.375.445 1.196 0 1.914-.843.727-.852.727-2.258v-.32zm2.867-.594v4.992h-1.437v-1.328q-.492.797-1.227 1.18-.734.375-1.797.375-1.343 0-2.14-.75-.79-.758-.79-2.024 0-1.476.985-2.226.992-.75 2.953-.75h2.016V8.75q0-.992-.656-1.531-.649-.547-1.829-.547-.75 0-1.46.18-.711.18-1.368.539V6.062q.79-.304 1.532-.453.742-.156 1.445-.156 1.898 0 2.836.984.937.985.937 2.985z"/>""", # noqa: E501
|
||||
"b": """<path d="M24.922 10.047q0-1.586-.656-2.485-.649-.906-1.79-.906-1.14 0-1.796.906-.649.899-.649 2.485 0 1.586.649 2.492.656.898 1.797.898 1.14 0 1.789-.898.656-.906.656-2.492zm-4.89-3.055q.452-.781 1.14-1.156.695-.383 1.656-.383 1.594 0 2.586 1.266 1 1.265 1 3.328 0 2.062-1 3.328-.992 1.266-2.586 1.266-.96 0-1.656-.375-.688-.383-1.14-1.164v1.312h-1.446V2.258h1.445z"/>""", # noqa: E501
|
||||
"c": """<path d="M25.96 6v1.344q-.608-.336-1.226-.5-.609-.172-1.234-.172-1.398 0-2.172.89-.773.883-.773 2.485 0 1.601.773 2.492.774.883 2.172.883.625 0 1.234-.164.618-.172 1.227-.508v1.328q-.602.281-1.25.422-.64.14-1.367.14-1.977 0-3.14-1.242-1.165-1.242-1.165-3.351 0-2.14 1.172-3.367 1.18-1.227 3.227-1.227.664 0 1.296.14.633.134 1.227.407z"/>""", # noqa: E501
|
||||
"d": """<path d="M24.973 6.992V2.258h1.437v12.156h-1.437v-1.312q-.453.78-1.149 1.164-.687.375-1.656.375-1.586 0-2.586-1.266-.992-1.266-.992-3.328 0-2.063.992-3.328 1-1.266 2.586-1.266.969 0 1.656.383.696.375 1.149 1.156zm-4.899 3.055q0 1.586.649 2.492.656.898 1.797.898 1.14 0 1.796-.898.657-.906.657-2.492 0-1.586-.657-2.485-.656-.906-1.796-.906-1.141 0-1.797.906-.649.899-.649 2.485z"/>""", # noqa: E501
|
||||
"e": """<path d="M26.555 9.68v.703h-6.61q.094 1.484.89 2.265.806.774 2.235.774.828 0 1.602-.203.781-.203 1.547-.61v1.36q-.774.328-1.586.5-.813.172-1.649.172-2.093 0-3.32-1.22-1.219-1.218-1.219-3.296 0-2.148 1.157-3.406 1.164-1.266 3.132-1.266 1.766 0 2.79 1.14 1.03 1.134 1.03 3.087zm-1.438-.422q-.015-1.18-.664-1.883-.64-.703-1.703-.703-1.203 0-1.93.68-.718.68-.828 1.914z"/>""", # noqa: E501
|
||||
"f": """<path d="M25.285 2.258v1.195H23.91q-.773 0-1.078.313-.297.312-.297 1.125v.773h2.367v1.117h-2.367v7.633H21.09V6.781h-1.375V5.664h1.375v-.61q0-1.46.68-2.124.68-.672 2.156-.672z"/>""", # noqa: E501
|
||||
"g": """<path d="M24.973 9.937q0-1.562-.649-2.421-.64-.86-1.804-.86-1.157 0-1.805.86-.64.859-.64 2.421 0 1.555.64 2.415.648.859 1.805.859 1.164 0 1.804-.86.649-.859.649-2.414zm1.437 3.391q0 2.234-.992 3.32-.992 1.094-3.04 1.094-.757 0-1.429-.117-.672-.11-1.304-.344v-1.398q.632.344 1.25.508.617.164 1.257.164 1.414 0 2.118-.743.703-.734.703-2.226v-.711q-.446.773-1.141 1.156-.695.383-1.664.383-1.61 0-2.594-1.227-.984-1.226-.984-3.25 0-2.03.984-3.257.985-1.227 2.594-1.227.969 0 1.664.383t1.14 1.156V5.664h1.438z"/>""", # noqa: E501
|
||||
"h": """<path d="M26.164 9.133v5.281h-1.437V9.18q0-1.243-.485-1.86-.484-.617-1.453-.617-1.164 0-1.836.742-.672.742-.672 2.024v4.945h-1.445V2.258h1.445v4.765q.516-.789 1.211-1.18.703-.39 1.617-.39 1.508 0 2.282.938.773.93.773 2.742z"/>""", # noqa: E501
|
||||
}
|
||||
|
||||
XX = """<g id="xx"><path d="M35.865 9.135a1.89 1.89 0 0 1 0 2.673L25.173 22.5l10.692 10.692a1.89 1.89 0 0 1 0 2.673 1.89 1.89 0 0 1-2.673 0L22.5 25.173 11.808 35.865a1.89 1.89 0 0 1-2.673 0 1.89 1.89 0 0 1 0-2.673L19.827 22.5 9.135 11.808a1.89 1.89 0 0 1 0-2.673 1.89 1.89 0 0 1 2.673 0L22.5 19.827 33.192 9.135a1.89 1.89 0 0 1 2.673 0z" fill="#000" stroke="#fff" stroke-width="1.688"/></g>""" # noqa: E501
|
||||
|
||||
CHECK_GRADIENT = """<radialGradient id="check_gradient" r="0.5"><stop offset="0%" stop-color="#ff0000" stop-opacity="1.0" /><stop offset="50%" stop-color="#e70000" stop-opacity="1.0" /><stop offset="100%" stop-color="#9e0000" stop-opacity="0.0" /></radialGradient>""" # noqa: E501
|
||||
|
||||
DEFAULT_COLORS = {
|
||||
"square light": "#ffce9e",
|
||||
"square dark": "#d18b47",
|
||||
"square dark lastmove": "#aaa23b",
|
||||
"square light lastmove": "#cdd16a",
|
||||
"margin": "#212121",
|
||||
"coord": "#e5e5e5",
|
||||
"arrow green": "#15781B80",
|
||||
"arrow red": "#88202080",
|
||||
"arrow yellow": "#e68f00b3",
|
||||
"arrow blue": "#00308880",
|
||||
}
|
||||
|
||||
|
||||
class Arrow:
|
||||
"""Details of an arrow to be drawn."""
|
||||
|
||||
tail: Square
|
||||
"""Start square of the arrow."""
|
||||
|
||||
head: Square
|
||||
"""End square of the arrow."""
|
||||
|
||||
color: str
|
||||
"""Arrow color."""
|
||||
|
||||
def __init__(self, tail: Square, head: Square, *, color: str = "green") -> None:
|
||||
self.tail = tail
|
||||
self.head = head
|
||||
self.color = color
|
||||
|
||||
def pgn(self) -> str:
|
||||
"""
|
||||
Returns the arrow in the format used by ``[%csl ...]`` and
|
||||
``[%cal ...]`` PGN annotations, e.g., ``Ga1`` or ``Ya2h2``.
|
||||
|
||||
Colors other than ``red``, ``yellow``, and ``blue`` default to green.
|
||||
"""
|
||||
if self.color == "red":
|
||||
color = "R"
|
||||
elif self.color == "yellow":
|
||||
color = "Y"
|
||||
elif self.color == "blue":
|
||||
color = "B"
|
||||
else:
|
||||
color = "G"
|
||||
|
||||
if self.tail == self.head:
|
||||
return f"{color}{chess.SQUARE_NAMES[self.tail]}"
|
||||
else:
|
||||
return f"{color}{chess.SQUARE_NAMES[self.tail]}{chess.SQUARE_NAMES[self.head]}"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.pgn()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Arrow({chess.SQUARE_NAMES[self.tail].upper()}, {chess.SQUARE_NAMES[self.head].upper()}, color={self.color!r})"
|
||||
|
||||
@classmethod
|
||||
def from_pgn(cls, pgn: str) -> Arrow:
|
||||
"""
|
||||
Parses an arrow from the format used by ``[%csl ...]`` and
|
||||
``[%cal ...]`` PGN annotations, e.g., ``Ga1`` or ``Ya2h2``.
|
||||
|
||||
Also allows skipping the color prefix, defaulting to green.
|
||||
|
||||
:raises: :exc:`ValueError` if the format is invalid.
|
||||
"""
|
||||
if pgn.startswith("G"):
|
||||
color = "green"
|
||||
pgn = pgn[1:]
|
||||
elif pgn.startswith("R"):
|
||||
color = "red"
|
||||
pgn = pgn[1:]
|
||||
elif pgn.startswith("Y"):
|
||||
color = "yellow"
|
||||
pgn = pgn[1:]
|
||||
elif pgn.startswith("B"):
|
||||
color = "blue"
|
||||
pgn = pgn[1:]
|
||||
else:
|
||||
color = "green"
|
||||
|
||||
tail = chess.parse_square(pgn[:2])
|
||||
head = chess.parse_square(pgn[2:]) if len(pgn) > 2 else tail
|
||||
return cls(tail, head, color=color)
|
||||
|
||||
|
||||
class SvgWrapper(str):
|
||||
def _repr_svg_(self) -> SvgWrapper:
|
||||
return self
|
||||
|
||||
|
||||
def _svg(viewbox: int, size: Optional[int]) -> ET.Element:
|
||||
svg = ET.Element("svg", {
|
||||
"xmlns": "http://www.w3.org/2000/svg",
|
||||
"xmlns:xlink": "http://www.w3.org/1999/xlink",
|
||||
"version": "1.2",
|
||||
"baseProfile": "tiny",
|
||||
"viewBox": f"0 0 {viewbox:d} {viewbox:d}",
|
||||
})
|
||||
|
||||
if size is not None:
|
||||
svg.set("width", str(size))
|
||||
svg.set("height", str(size))
|
||||
|
||||
return svg
|
||||
|
||||
|
||||
def _attrs(attrs: Dict[str, Union[str, int, float, None]]) -> Dict[str, str]:
|
||||
return {k: str(v) for k, v in attrs.items() if v is not None}
|
||||
|
||||
|
||||
def _color(colors: Dict[str, str], color: str) -> Tuple[str, float]:
|
||||
color = colors.get(color, DEFAULT_COLORS[color])
|
||||
if color.startswith("#"):
|
||||
try:
|
||||
if len(color) == 5:
|
||||
return color[:4], int(color[4], 16) / 0xf
|
||||
elif len(color) == 9:
|
||||
return color[:7], int(color[7:], 16) / 0xff
|
||||
except ValueError:
|
||||
pass # Ignore invalid hex value
|
||||
return color, 1.0
|
||||
|
||||
|
||||
def _coord(text: str, x: int, y: int, width: int, height: int, horizontal: bool, margin: int, *, color: str, opacity: float) -> ET.Element:
|
||||
scale = margin / MARGIN
|
||||
|
||||
if horizontal:
|
||||
x += int(width - scale * width) // 2
|
||||
else:
|
||||
y += int(height - scale * height) // 2
|
||||
|
||||
t = ET.Element("g", _attrs({
|
||||
"transform": f"translate({x}, {y}) scale({scale}, {scale})",
|
||||
"fill": color,
|
||||
"stroke": color,
|
||||
"opacity": opacity if opacity < 1.0 else None,
|
||||
}))
|
||||
t.append(ET.fromstring(COORDS[text]))
|
||||
return t
|
||||
|
||||
|
||||
def piece(piece: chess.Piece, size: Optional[int] = None) -> str:
|
||||
"""
|
||||
Renders the given :class:`chess.Piece` as an SVG image.
|
||||
|
||||
>>> import chess
|
||||
>>> import chess.svg
|
||||
>>>
|
||||
>>> chess.svg.piece(chess.Piece.from_symbol("R")) # doctest: +SKIP
|
||||
|
||||
.. image:: ../docs/wR.svg
|
||||
:alt: R
|
||||
"""
|
||||
svg = _svg(SQUARE_SIZE, size)
|
||||
svg.append(ET.fromstring(PIECES[piece.symbol()]))
|
||||
return SvgWrapper(ET.tostring(svg).decode("utf-8"))
|
||||
|
||||
|
||||
def board(board: Optional[chess.BaseBoard] = None, *,
|
||||
orientation: Color = chess.WHITE,
|
||||
lastmove: Optional[chess.Move] = None,
|
||||
check: Optional[Square] = None,
|
||||
arrows: Iterable[Union[Arrow, Tuple[Square, Square]]] = [],
|
||||
squares: Optional[IntoSquareSet] = None,
|
||||
size: Optional[int] = None,
|
||||
coordinates: bool = True,
|
||||
colors: Dict[str, str] = {},
|
||||
flipped: bool = False,
|
||||
style: Optional[str] = None) -> str:
|
||||
"""
|
||||
Renders a board with pieces and/or selected squares as an SVG image.
|
||||
|
||||
:param board: A :class:`chess.BaseBoard` for a chessboard with pieces, or
|
||||
``None`` (the default) for a chessboard without pieces.
|
||||
:param orientation: The point of view, defaulting to ``chess.WHITE``.
|
||||
:param lastmove: A :class:`chess.Move` to be highlighted.
|
||||
:param check: A square to be marked indicating a check.
|
||||
:param arrows: A list of :class:`~chess.svg.Arrow` objects, like
|
||||
``[chess.svg.Arrow(chess.E2, chess.E4)]``, or a list of tuples, like
|
||||
``[(chess.E2, chess.E4)]``. An arrow from a square pointing to the same
|
||||
square is drawn as a circle, like ``[(chess.E2, chess.E2)]``.
|
||||
:param squares: A :class:`chess.SquareSet` with selected squares.
|
||||
:param size: The size of the image in pixels (e.g., ``400`` for a 400 by
|
||||
400 board), or ``None`` (the default) for no size limit.
|
||||
:param coordinates: Pass ``False`` to disable the coordinate margin.
|
||||
:param colors: A dictionary to override default colors. Possible keys are
|
||||
``square light``, ``square dark``, ``square light lastmove``,
|
||||
``square dark lastmove``, ``margin``, ``coord``, ``arrow green``,
|
||||
``arrow blue``, ``arrow red``, and ``arrow yellow``. Values should look
|
||||
like ``#ffce9e`` (opaque), or ``#15781B80`` (transparent).
|
||||
:param flipped: Pass ``True`` to flip the board.
|
||||
:param style: A CSS stylesheet to include in the SVG image.
|
||||
|
||||
>>> import chess
|
||||
>>> import chess.svg
|
||||
>>>
|
||||
>>> board = chess.Board("8/8/8/8/4N3/8/8/8 w - - 0 1")
|
||||
>>> squares = board.attacks(chess.E4)
|
||||
>>> chess.svg.board(board, squares=squares, size=350) # doctest: +SKIP
|
||||
|
||||
.. image:: ../docs/Ne4.svg
|
||||
:alt: 8/8/8/8/4N3/8/8/8
|
||||
|
||||
.. deprecated:: 1.1
|
||||
Use *orientation* with a color instead of the *flipped* toggle.
|
||||
"""
|
||||
orientation ^= flipped
|
||||
margin = 15 if coordinates else 0
|
||||
svg = _svg(8 * SQUARE_SIZE + 2 * margin, size)
|
||||
|
||||
if style:
|
||||
ET.SubElement(svg, "style").text = style
|
||||
|
||||
defs = ET.SubElement(svg, "defs")
|
||||
if board:
|
||||
for piece_color in chess.COLORS:
|
||||
for piece_type in chess.PIECE_TYPES:
|
||||
if board.pieces_mask(piece_type, piece_color):
|
||||
defs.append(ET.fromstring(PIECES[chess.Piece(piece_type, piece_color).symbol()]))
|
||||
|
||||
squares = chess.SquareSet(squares) if squares else chess.SquareSet()
|
||||
if squares:
|
||||
defs.append(ET.fromstring(XX))
|
||||
|
||||
if check is not None:
|
||||
defs.append(ET.fromstring(CHECK_GRADIENT))
|
||||
|
||||
# Render coordinates.
|
||||
if coordinates:
|
||||
margin_color, margin_opacity = _color(colors, "margin")
|
||||
ET.SubElement(svg, "rect", _attrs({
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 2 * margin + 8 * SQUARE_SIZE,
|
||||
"height": 2 * margin + 8 * SQUARE_SIZE,
|
||||
"fill": margin_color,
|
||||
"opacity": margin_opacity if margin_opacity < 1.0 else None,
|
||||
}))
|
||||
coord_color, coord_opacity = _color(colors, "coord")
|
||||
for file_index, file_name in enumerate(chess.FILE_NAMES):
|
||||
x = (file_index if orientation else 7 - file_index) * SQUARE_SIZE + margin
|
||||
svg.append(_coord(file_name, x, 0, SQUARE_SIZE, margin, True, margin, color=coord_color, opacity=coord_opacity))
|
||||
svg.append(_coord(file_name, x, margin + 8 * SQUARE_SIZE, SQUARE_SIZE, margin, True, margin, color=coord_color, opacity=coord_opacity))
|
||||
for rank_index, rank_name in enumerate(chess.RANK_NAMES):
|
||||
y = (7 - rank_index if orientation else rank_index) * SQUARE_SIZE + margin
|
||||
svg.append(_coord(rank_name, 0, y, margin, SQUARE_SIZE, False, margin, color=coord_color, opacity=coord_opacity))
|
||||
svg.append(_coord(rank_name, margin + 8 * SQUARE_SIZE, y, margin, SQUARE_SIZE, False, margin, color=coord_color, opacity=coord_opacity))
|
||||
|
||||
# Render board.
|
||||
for square, bb in enumerate(chess.BB_SQUARES):
|
||||
file_index = chess.square_file(square)
|
||||
rank_index = chess.square_rank(square)
|
||||
|
||||
x = (file_index if orientation else 7 - file_index) * SQUARE_SIZE + margin
|
||||
y = (7 - rank_index if orientation else rank_index) * SQUARE_SIZE + margin
|
||||
|
||||
cls = ["square", "light" if chess.BB_LIGHT_SQUARES & bb else "dark"]
|
||||
if lastmove and square in [lastmove.from_square, lastmove.to_square]:
|
||||
cls.append("lastmove")
|
||||
fill_color, fill_opacity = _color(colors, " ".join(cls))
|
||||
|
||||
cls.append(chess.SQUARE_NAMES[square])
|
||||
|
||||
ET.SubElement(svg, "rect", _attrs({
|
||||
"x": x,
|
||||
"y": y,
|
||||
"width": SQUARE_SIZE,
|
||||
"height": SQUARE_SIZE,
|
||||
"class": " ".join(cls),
|
||||
"stroke": "none",
|
||||
"fill": fill_color,
|
||||
"opacity": fill_opacity if fill_opacity < 1.0 else None,
|
||||
}))
|
||||
|
||||
# Render check mark.
|
||||
if check is not None:
|
||||
file_index = chess.square_file(check)
|
||||
rank_index = chess.square_rank(check)
|
||||
|
||||
x = (file_index if orientation else 7 - file_index) * SQUARE_SIZE + margin
|
||||
y = (7 - rank_index if orientation else rank_index) * SQUARE_SIZE + margin
|
||||
|
||||
ET.SubElement(svg, "rect", _attrs({
|
||||
"x": x,
|
||||
"y": y,
|
||||
"width": SQUARE_SIZE,
|
||||
"height": SQUARE_SIZE,
|
||||
"class": "check",
|
||||
"fill": "url(#check_gradient)",
|
||||
}))
|
||||
|
||||
# Render pieces and selected squares.
|
||||
for square, bb in enumerate(chess.BB_SQUARES):
|
||||
file_index = chess.square_file(square)
|
||||
rank_index = chess.square_rank(square)
|
||||
|
||||
x = (file_index if orientation else 7 - file_index) * SQUARE_SIZE + margin
|
||||
y = (7 - rank_index if orientation else rank_index) * SQUARE_SIZE + margin
|
||||
|
||||
if board is not None:
|
||||
piece = board.piece_at(square)
|
||||
if piece:
|
||||
href = f"#{chess.COLOR_NAMES[piece.color]}-{chess.PIECE_NAMES[piece.piece_type]}"
|
||||
ET.SubElement(svg, "use", {
|
||||
"href": href,
|
||||
"xlink:href": href,
|
||||
"transform": f"translate({x:d}, {y:d})",
|
||||
})
|
||||
|
||||
# Render selected squares.
|
||||
if squares is not None and square in squares:
|
||||
ET.SubElement(svg, "use", _attrs({
|
||||
"href": "#xx",
|
||||
"xlink:href": "#xx",
|
||||
"x": x,
|
||||
"y": y,
|
||||
}))
|
||||
|
||||
# Render arrows.
|
||||
for arrow in arrows:
|
||||
try:
|
||||
tail, head, color = arrow.tail, arrow.head, arrow.color # type: ignore
|
||||
except AttributeError:
|
||||
tail, head = arrow # type: ignore
|
||||
color = "green"
|
||||
|
||||
try:
|
||||
color, opacity = _color(colors, " ".join(["arrow", color]))
|
||||
except KeyError:
|
||||
opacity = 1.0
|
||||
|
||||
tail_file = chess.square_file(tail)
|
||||
tail_rank = chess.square_rank(tail)
|
||||
head_file = chess.square_file(head)
|
||||
head_rank = chess.square_rank(head)
|
||||
|
||||
xtail = margin + (tail_file + 0.5 if orientation else 7.5 - tail_file) * SQUARE_SIZE
|
||||
ytail = margin + (7.5 - tail_rank if orientation else tail_rank + 0.5) * SQUARE_SIZE
|
||||
xhead = margin + (head_file + 0.5 if orientation else 7.5 - head_file) * SQUARE_SIZE
|
||||
yhead = margin + (7.5 - head_rank if orientation else head_rank + 0.5) * SQUARE_SIZE
|
||||
|
||||
if (head_file, head_rank) == (tail_file, tail_rank):
|
||||
ET.SubElement(svg, "circle", _attrs({
|
||||
"cx": xhead,
|
||||
"cy": yhead,
|
||||
"r": SQUARE_SIZE * 0.9 / 2,
|
||||
"stroke-width": SQUARE_SIZE * 0.1,
|
||||
"stroke": color,
|
||||
"opacity": opacity if opacity < 1.0 else None,
|
||||
"fill": "none",
|
||||
"class": "circle",
|
||||
}))
|
||||
else:
|
||||
marker_size = 0.75 * SQUARE_SIZE
|
||||
marker_margin = 0.1 * SQUARE_SIZE
|
||||
|
||||
dx, dy = xhead - xtail, yhead - ytail
|
||||
hypot = math.hypot(dx, dy)
|
||||
|
||||
shaft_x = xhead - dx * (marker_size + marker_margin) / hypot
|
||||
shaft_y = yhead - dy * (marker_size + marker_margin) / hypot
|
||||
|
||||
xtip = xhead - dx * marker_margin / hypot
|
||||
ytip = yhead - dy * marker_margin / hypot
|
||||
|
||||
ET.SubElement(svg, "line", _attrs({
|
||||
"x1": xtail,
|
||||
"y1": ytail,
|
||||
"x2": shaft_x,
|
||||
"y2": shaft_y,
|
||||
"stroke": color,
|
||||
"opacity": opacity if opacity < 1.0 else None,
|
||||
"stroke-width": SQUARE_SIZE * 0.2,
|
||||
"stroke-linecap": "butt",
|
||||
"class": "arrow",
|
||||
}))
|
||||
|
||||
marker = [(xtip, ytip),
|
||||
(shaft_x + dy * 0.5 * marker_size / hypot,
|
||||
shaft_y - dx * 0.5 * marker_size / hypot),
|
||||
(shaft_x - dy * 0.5 * marker_size / hypot,
|
||||
shaft_y + dx * 0.5 * marker_size / hypot)]
|
||||
|
||||
ET.SubElement(svg, "polygon", _attrs({
|
||||
"points": " ".join(f"{x},{y}" for x, y in marker),
|
||||
"fill": color,
|
||||
"opacity": opacity if opacity < 1.0 else None,
|
||||
"class": "arrow",
|
||||
}))
|
||||
|
||||
return SvgWrapper(ET.tostring(svg).decode("utf-8"))
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import chess.pgn
|
||||
import logging
|
||||
|
||||
logging.getLogger("chess.pgn").setLevel(logging.CRITICAL)
|
||||
|
||||
pgn = open("/mnt/cartesi-python-chess/chess-game.pgn")
|
||||
game = chess.pgn.read_game(pgn)
|
||||
game.errors
|
||||
|
||||
print(("Errors:"), game.errors)
|
||||
|
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -x
|
||||
|
||||
./edit-rootfs-cartesi-cartesi-python-chess
|
||||
./edit-mntfs-cartesi-cartesi-python-chess
|
||||
./build-cartesi-cartesi-python-chess
|
||||
./run-cartesi-cartesi-python-chess
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
vim cartesi-python-chess-cartesi-img/cartesi-python-chess.sh
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
MYDIR=`pwd`
|
||||
|
||||
cd /home/jebba/devel/cartesi/machine-emulator-sdk/fs
|
||||
|
||||
make config
|
||||
|
||||
cp -p ~/devel/cartesi/machine-emulator-sdk/fs/cartesi-buildroot-config \
|
||||
$MYDIR/
|
||||
|
||||
cp -p /home/jebba/devel/cartesi/machine-emulator-sdk/fs/rootfs.ext2 \
|
||||
/opt/cartesi/share/images/rootfs-cartesi-python-chess.ext2
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Launch virtual machine with pre-built root image with cartesi-python-chess
|
||||
# and cartesi-python-chess.sh script in new image that gets run at boot
|
||||
cartesi-machine \
|
||||
--flash-drive=label:cartesi-python-chess,filename:cartesi-python-chess.ext2 \
|
||||
--flash-drive=label:root,filename:/opt/cartesi/share/images/rootfs-cartesi-python-chess.ext2 \
|
||||
-- /mnt/cartesi-python-chess/cartesi-python-chess.sh
|
||||
|
Loading…
Reference in New Issue