2 个版本 (1 个稳定版本)
1.0.0 | 2024年6月16日 |
---|---|
0.2.0 | 2024年6月1日 |
0.1.1 |
|
0.1.0 |
|
175 在 文本处理 中
140KB
2K SLoC
rschess

一个旨在尽可能丰富的 Rust 国际象棋库
目录
目标
该项目旨在尽可能丰富功能,以性能为代价(这可能在将来改变)。令人惊讶的是,Rust 的 crate 中能提供足够功能的与国际象棋相关的应用非常少。使用 rschess,我努力创建一个库,提供开发国际象棋软件所需的所有必要功能。
功能
解析 FEN
use rschess::{Board, Fen};
let board = Board::from_fen(Fen::try_from("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50").unwrap());
let starting_position = Board::default(); // equivalent to Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1".try_into().unwrap())
解析 PGN
Carlsen-Karjakin_WCC2016_R13_4.pgn
[Event "Carlsen - Karjakin World Championship Match"]
[Site "New York, NY USA"]
[Date "2016.11.30"]
[EventDate "2016.11.11"]
[Round "13.4"]
[Result "1-0"]
[White "Magnus Carlsen"]
[Black "Sergey Karjakin"]
[ECO "B54"]
[WhiteElo "?"]
[BlackElo "?"]
[PlyCount "99"]
1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.f3 e5 6.Nb3 Be7 7.c4
a5 8.Be3 a4 9.Nc1 O-O 10.Nc3 Qa5 11.Qd2 Na6 12.Be2 Nc5 13.O-O
Bd7 14.Rb1 Rfc8 15.b4 axb3 16.axb3 Qd8 17.Nd3 Ne6 18.Nb4 Bc6
19.Rfd1 h5 20.Bf1 h4 21.Qf2 Nd7 22.g3 Ra3 23.Bh3 Rca8 24.Nc2
R3a6 25.Nb4 Ra5 26.Nc2 b6 27.Rd2 Qc7 28.Rbd1 Bf8 29.gxh4 Nf4
30.Bxf4 exf4 31.Bxd7 Qxd7 32.Nb4 Ra3 33.Nxc6 Qxc6 34.Nb5 Rxb3
35.Nd4 Qxc4 36.Nxb3 Qxb3 37.Qe2 Be7 38.Kg2 Qe6 39.h5 Ra3
40.Rd3 Ra2 41.R3d2 Ra3 42.Rd3 Ra7 43.Rd5 Rc7 44.Qd2 Qf6 45.Rf5
Qh4 46.Rc1 Ra7 47.Qxf4 Ra2+ 48.Kh1 Qf2 49.Rc8+ Kh7 50.Qh6+ 1-0
use rschess::{Board, Pgn};
let pgn = Pgn::try_from(include_str!("Carlsen-Karjakin_WCC2016_R13_4.pgn")).unwrap();
let board = pgn.board(); // &Board
assert_eq!(Board::from_fen("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50".try_into().unwrap()).position(), board.position());
在上面的示例中,两个 Board
不相等,但它们的 Position
是相同的,因为 Pgn
通过文本中的“'1-0'”识别出白方因投降而获胜,而 Fen
则不这样做(因为 FEN 文本不包含关于游戏结果的信息)。
生成合法走法
use rschess::Board;
let board = Board::from_fen("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50".try_into().unwrap());
let legal_moves = board.gen_legal_moves();
assert_eq!(legal_moves.len(), 2);
请注意,游戏结束后没有合法的走法。
移动棋子
use rschess::{Board, Move};
let mut board = Board::default();
// move from UCI
board.make_move(Move::from_uci("e2e4").unwrap()).unwrap();
// or shortened:
board.make_move_uci("c7c5").unwrap();
// move from SAN
board.make_move(board.san_to_move("Nc3").unwrap()).unwrap();
// or shortened:
board.make_move_san("Nc6").unwrap();
// print all legal moves in UCI
println!("{:?}", board.gen_legal_moves().iter().map(Move::to_uci).collect::<Vec<_>>());
// print all legal moves in SAN
println!("{:?}", board.gen_legal_moves().into_iter().map(|m| board.move_to_san(m).unwrap()).collect::<Vec<_>>());
输出
["a1b1", "d1e2", "d1f3", "d1g4", "d1h5", "e1e2", "f1e2", "f1d3", "f1c4", "f1b5", "f1a6", "g1e2", "g1f3", "g1h3", "a2a3", "a2a4", "b2b3", "b2b4", "d2d3", "d2d4", "f2f3", "f2f4", "g2g3", "g2g4", "h2h3", "h2h4", "c3a4", "c3b5", "c3d5", "c3e2", "c3b1", "e4e5"]
["Rb1", "Qe2", "Qf3", "Qg4", "Qh5", "Ke2", "Be2", "Bd3", "Bc4", "Bb5", "Ba6", "Nge2", "Nf3", "Nh3", "a3", "a4", "b3", "b4", "d3", "d4", "f3", "f4", "g3", "g4", "h3", "h4", "Na4", "Nb5", "Nd5", "Nce2", "Nb1", "e5"]
棋盘状态
use rschess::{Board, Color, GameResult, WinType};
let start_pos = Board::default();
assert!(start_pos.is_ongoing());
assert_eq!(start_pos.stalemated_side(), None);
assert_eq!(start_pos.game_result(), None);
let mut board = Board::from_fen("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50".try_into().unwrap());
board.make_move_san("gxh6").unwrap();
board.make_move_san("Rxf7#").unwrap();
assert!(board.is_game_over());
assert!(board.is_checkmate());
assert_eq!(board.checkmated_side(), Some(Color::Black));
assert_eq!(board.game_result(), Some(GameResult::Wins(Color::White, WinType::Checkmate)));
rschess 检测到
- 将军
- 长将
- 三次重复
- 缺乏将军物质
- 五十回合规则
- 五次重复
- 七十五回合规则。
请注意,三次重复和五十回合规则不会立即结束游戏,因为这些是必须由玩家声称的平局类型。
生成 FEN
use rschess::Board;
let board = Board::default();
let fen = board.to_fen(); // returns a Fen object
assert_eq!(fen.to_string(), "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
生成 PGN
从 PGN 文本
M290-study.pgn
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "1-0"]
[SetUp "1"]
[FEN "bBrb1B2/P1n1r2p/1Kp1Pb1p/2pk1P1p/5P2/1P2pP2/1pP1P3/1R4n1 w - - 0 1"]
1. Rd1+ Bd4 2. c4+ Kd6 3. Rxg1 Bc3 4. Rd1+ Bd4 5. Ka5 Bb7 6. Ka4 Ba8 7. Ka3 Bb7
8. Ka2 Ba8 9. Kb1 Bb7 10. Kc2 Ba8 11. Kd3 Bb7 12. Re1 Ba8 13. Rf1 Bb7 14. Rd1
Ba8 15. Kc2 Bb7 16. Kb1 Ba8 17. Ka2 Bb7 18. Ka3 Ba8 19. Ka4 Bb7 20. Ka5 Ba8 21.
Kb6 h4 22. Ka5 Bb7 23. Ka4 Ba8 24. Ka3 Bb7 25. Ka2 Ba8 26. Kb1 Bb7 27. Kc2 Ba8
28. Kd3 Bb7 29. Rf1 Ba8 30. Re1 Bb7 31. Rd1 Ba8 32. Kc2 Bb7 33. Kb1 Ba8 34. Ka2
Bb7 35. Ka3 Ba8 36. Ka4 Bb7 37. Ka5 Ba8 38. Kb6 h3 39. Ka5 Bb7 40. Ka4 Ba8 41.
Ka3 Bb7 42. Ka2 Ba8 43. Kb1 Bb7 44. Kc2 Ba8 45. Kd3 Bb7 46. Rf1 Ba8 47. Re1 Bb7
48. Rd1 Ba8 49. Kc2 Bb7 50. Kb1 Ba8 51. Ka2 Bb7 52. Ka3 Ba8 53. Ka4 Bb7 54. Ka5
Ba8 55. Kb6 h2 56. Ka5 Bb7 57. Ka4 Ba8 58. Ka3 Bb7 59. Ka2 Ba8 60. Kb1 Bb7 61.
Kc2 Ba8 62. Kd3 Bb7 63. Rf1 Ba8 64. Re1 Bb7 65. Rd1 Ba8 66. Kc2 Bb7 67. Kb1 Ba8
68. Ka2 Bb7 69. Ka3 Ba8 70. Ka4 Bb7 71. Ka5 Ba8 72. Kb6 h5 73. Ka5 Bb7 74. Ka4
Ba8 75. Ka3 Bb7 76. Ka2 Ba8 77. Kb1 Bb7 78. Kc2 Ba8 79. Kd3 Bb7 80. Rf1 Ba8 81.
Re1 Bb7 82. Rd1 Ba8 83. Kc2 Bb7 84. Kb1 Ba8 85. Ka2 Bb7 86. Ka3 Ba8 87. Ka4 Bb7
88. Ka5 Ba8 89. Kb6 h4 90. Ka5 Bb7 91. Ka4 Ba8 92. Ka3 Bb7 93. Ka2 Ba8 94. Kb1
Bb7 95. Kc2 Ba8 96. Kd3 Bb7 97. Rf1 Ba8 98. Re1 Bb7 99. Rd1 Ba8 100. Kc2 Bb7
101. Kb1 Ba8 102. Ka2 Bb7 103. Ka3 Ba8 104. Ka4 Bb7 105. Ka5 Ba8 106. Kb6 h3
107. Ka5 Bb7 108. Ka4 Ba8 109. Ka3 Bb7 110. Ka2 Ba8 111. Kb1 Bb7 112. Kc2 Ba8
113. Kd3 Bb7 114. Rf1 Ba8 115. Re1 Bb7 116. Rd1 Ba8 117. Kc2 Bb7 118. Kb1 Ba8
119. Ka2 Bb7 120. Ka3 Ba8 121. Ka4 Bb7 122. Ka5 Ba8 123. Kb6 h6 124. Ka5 Bb7
125. Ka4 Ba8 126. Ka3 Bb7 127. Ka2 Ba8 128. Kb1 Bb7 129. Kc2 Ba8 130. Kd3 Bb7
131. Rf1 Ba8 132. Re1 Bb7 133. Rd1 Ba8 134. Kc2 Bb7 135. Kb1 Ba8 136. Ka2 Bb7
137. Ka3 Ba8 138. Ka4 Bb7 139. Ka5 Ba8 140. Kb6 h5 141. Ka5 Bb7 142. Ka4 Ba8
143. Ka3 Bb7 144. Ka2 Ba8 145. Kb1 Bb7 146. Kc2 Ba8 147. Kd3 Bb7 148. Rf1 Ba8
149. Re1 Bb7 150. Rd1 Ba8 151. Kc2 Bb7 152. Kb1 Ba8 153. Ka2 Bb7 154. Ka3 Ba8
155. Ka4 Bb7 156. Ka5 Ba8 157. Kb6 h4 158. Ka5 Bb7 159. Ka4 Ba8 160. Ka3 Bb7
161. Ka2 Ba8 162. Kb1 Bb7 163. Kc2 Ba8 164. Kd3 Bb7 165. Rf1 Ba8 166. Re1 Bb7
167. Rd1 Ba8 168. Kc2 Bb7 169. Kb1 Ba8 170. Ka2 Bb7 171. Ka3 Ba8 172. Ka4 Bb7
173. Ka5 Ba8 174. Kb6 h1=Q 175. Rxh1 Bg7 176. Rd1+ Bd4 177. Ka5 Bb7 178. Ka4 Ba8
179. Ka3 Bb7 180. Ka2 Ba8 181. Kb1 Bb7 182. Kc2 Ba8 183. Kd3 Bb7 184. Rf1 Ba8
185. Re1 Bb7 186. Rd1 Ba8 187. Kc2 Bb7 188. Kb1 Ba8 189. Ka2 Bb7 190. Ka3 Ba8
191. Ka4 Bb7 192. Ka5 Ba8 193. Kb6 h2 194. Ka5 Bb7 195. Ka4 Ba8 196. Ka3 Bb7
197. Ka2 Ba8 198. Kb1 Bb7 199. Kc2 Ba8 200. Kd3 Bb7 201. Rf1 Ba8 202. Re1 Bb7
203. Rd1 Ba8 204. Kc2 Bb7 205. Kb1 Ba8 206. Ka2 Bb7 207. Ka3 Ba8 208. Ka4 Bb7
209. Ka5 Ba8 210. Kb6 h3 211. Ka5 Bb7 212. Ka4 Ba8 213. Ka3 Bb7 214. Ka2 Ba8
215. Kb1 Bb7 216. Kc2 Ba8 217. Kd3 Bb7 218. Rf1 Ba8 219. Re1 Bb7 220. Rd1 Ba8
221. Kc2 Bb7 222. Kb1 Ba8 223. Ka2 Bb7 224. Ka3 Ba8 225. Ka4 Bb7 226. Ka5 Ba8
227. Kb6 h1=Q 228. Rxh1 Bg7 229. Rd1+ Bd4 230. Ka5 Bb7 231. Ka4 Ba8 232. Ka3 Bb7
233. Ka2 Ba8 234. Kb1 Bb7 235. Kc2 Ba8 236. Kd3 Bb7 237. Rf1 Ba8 238. Re1 Bb7
239. Rd1 Ba8 240. Kc2 Bb7 241. Kb1 Ba8 242. Ka2 Bb7 243. Ka3 Ba8 244. Ka4 Bb7
245. Ka5 Ba8 246. Kb6 h2 247. Ka5 Bb7 248. Ka4 Ba8 249. Ka3 Bb7 250. Ka2 Ba8
251. Kb1 Bb7 252. Kc2 Ba8 253. Kd3 Bb7 254. Rf1 Ba8 255. Re1 Bb7 256. Rd1 Ba8
257. Kc2 Bb7 258. Kb1 Ba8 259. Ka2 Bb7 260. Ka3 Ba8 261. Ka4 Bb7 262. Ka5 Ba8
263. Kb6 h1=Q 264. Rxh1 Bg7 265. Rd1+ Bd4 266. Ka5 Bb7 267. Ka4 Ba8 268. Ka3 Bb7
269. Ka2 Ba8 270. Kb1 Bb7 271. Kc2 Ba8 272. Kd3 Bb7 273. Rf1 Ba8 274. Re1 Bb7
275. Rd1 Ba8 276. Kc2 Bb7 277. Kb1 Ba8 278. Ka2 Bb7 279. Ka3 Ba8 280. Ka4 Bb7
281. Ka5 Ba8 282. Kb6 Bb7 283. Kxb7 b1=Q 284. Rxb1 Be5 285. Rd1+ Bd4 286. Rxd4+
cxd4 287. Kb6 d3 288. a8=Q Rxb8+ 289. Qxb8 dxe2 290. Qxd8# 1-0
use rschess::Pgn;
let pgn = Pgn::try_from(include_str!("M290-study.pgn")).unwrap();
println!("{pgn}");
assert!(pgn.to_string().contains(&pgn.board().gen_movetext()));
Board::gen_movetext
生成了游戏的SAN移动文本,不包括游戏结果。还应注意,PGN文本必须遵循七个标签花名册。
输出
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "1-0"]
[FEN "bBrb1B2/P1n1r2p/1Kp1Pb1p/2pk1P1p/5P2/1P2pP2/1pP1P3/1R4n1 w - - 0 1"]
[SetUp "1"]
1. Rd1+ Bd4 2. c4+ Kd6 3. Rxg1 Bc3 4. Rd1+ Bd4 5. Ka5 Bb7 6. Ka4 Ba8 7. Ka3 Bb7 8. Ka2 Ba8 9. Kb1 Bb7 10. Kc2 Ba8 11. Kd3 Bb7 12. Re1 Ba8 13. Rf1 Bb7 14. Rd1 Ba8 15. Kc2 Bb7 16. Kb1 Ba8 17. Ka2 Bb7 18. Ka3 Ba8 19. Ka4 Bb7 20. Ka5 Ba8 21. Kb6 h4 22. Ka5 Bb7 23. Ka4 Ba8 24. Ka3 Bb7 25. Ka2 Ba8 26. Kb1 Bb7 27. Kc2 Ba8 28. Kd3 Bb7 29. Rf1 Ba8 30. Re1 Bb7 31. Rd1 Ba8 32. Kc2 Bb7 33. Kb1 Ba8 34. Ka2 Bb7 35. Ka3 Ba8 36. Ka4 Bb7 37. Ka5 Ba8 38. Kb6 h3 39. Ka5 Bb7 40. Ka4 Ba8 41. Ka3 Bb7 42. Ka2 Ba8 43. Kb1 Bb7 44. Kc2 Ba8 45. Kd3 Bb7 46. Rf1 Ba8 47. Re1 Bb7 48. Rd1 Ba8 49. Kc2 Bb7 50. Kb1 Ba8 51. Ka2 Bb7 52. Ka3 Ba8 53. Ka4 Bb7 54. Ka5 Ba8 55. Kb6 h2 56. Ka5 Bb7 57. Ka4 Ba8 58. Ka3 Bb7 59. Ka2 Ba8 60. Kb1 Bb7 61. Kc2 Ba8 62. Kd3 Bb7 63. Rf1 Ba8 64. Re1 Bb7 65. Rd1 Ba8 66. Kc2 Bb7 67. Kb1 Ba8 68. Ka2 Bb7 69. Ka3 Ba8 70. Ka4 Bb7 71. Ka5 Ba8 72. Kb6 h5 73. Ka5 Bb7 74. Ka4 Ba8 75. Ka3 Bb7 76. Ka2 Ba8 77. Kb1 Bb7 78. Kc2 Ba8 79. Kd3 Bb7 80. Rf1 Ba8 81. Re1 Bb7 82. Rd1 Ba8 83. Kc2 Bb7 84. Kb1 Ba8 85. Ka2 Bb7 86. Ka3 Ba8 87. Ka4 Bb7 88. Ka5 Ba8 89. Kb6 h4 90. Ka5 Bb7 91. Ka4 Ba8 92. Ka3 Bb7 93. Ka2 Ba8 94. Kb1 Bb7 95. Kc2 Ba8 96. Kd3 Bb7 97. Rf1 Ba8 98. Re1 Bb7 99. Rd1 Ba8 100. Kc2 Bb7 101. Kb1 Ba8 102. Ka2 Bb7 103. Ka3 Ba8 104. Ka4 Bb7 105. Ka5 Ba8 106. Kb6 h3 107. Ka5 Bb7 108. Ka4 Ba8 109. Ka3 Bb7 110. Ka2 Ba8 111. Kb1 Bb7 112. Kc2 Ba8 113. Kd3 Bb7 114. Rf1 Ba8 115. Re1 Bb7 116. Rd1 Ba8 117. Kc2 Bb7 118. Kb1 Ba8 119. Ka2 Bb7 120. Ka3 Ba8 121. Ka4 Bb7 122. Ka5 Ba8 123. Kb6 h6 124. Ka5 Bb7 125. Ka4 Ba8 126. Ka3 Bb7 127. Ka2 Ba8 128. Kb1 Bb7 129. Kc2 Ba8 130. Kd3 Bb7 131. Rf1 Ba8 132. Re1 Bb7 133. Rd1 Ba8 134. Kc2 Bb7 135. Kb1 Ba8 136. Ka2 Bb7 137. Ka3 Ba8 138. Ka4 Bb7 139. Ka5 Ba8 140. Kb6 h5 141. Ka5 Bb7 142. Ka4 Ba8 143. Ka3 Bb7 144. Ka2 Ba8 145. Kb1 Bb7 146. Kc2 Ba8 147. Kd3 Bb7 148. Rf1 Ba8 149. Re1 Bb7 150. Rd1 Ba8 151. Kc2 Bb7 152. Kb1 Ba8 153. Ka2 Bb7 154. Ka3 Ba8 155. Ka4 Bb7 156. Ka5 Ba8 157. Kb6 h4 158. Ka5 Bb7 159. Ka4 Ba8 160. Ka3 Bb7 161. Ka2 Ba8 162. Kb1 Bb7 163. Kc2 Ba8 164. Kd3 Bb7 165. Rf1 Ba8 166. Re1 Bb7 167. Rd1 Ba8 168. Kc2 Bb7 169. Kb1 Ba8 170. Ka2 Bb7 171. Ka3 Ba8 172. Ka4 Bb7 173. Ka5 Ba8 174. Kb6 h1=Q 175. Rxh1 Bg7 176. Rd1+ Bd4 177. Ka5 Bb7 178. Ka4 Ba8 179. Ka3 Bb7 180. Ka2 Ba8 181. Kb1 Bb7 182. Kc2 Ba8 183. Kd3 Bb7 184. Rf1 Ba8 185. Re1 Bb7 186. Rd1 Ba8 187. Kc2 Bb7 188. Kb1 Ba8 189. Ka2 Bb7 190. Ka3 Ba8 191. Ka4 Bb7 192. Ka5 Ba8 193. Kb6 h2 194. Ka5 Bb7 195. Ka4 Ba8 196. Ka3 Bb7 197. Ka2 Ba8 198. Kb1 Bb7 199. Kc2 Ba8 200. Kd3 Bb7 201. Rf1 Ba8 202. Re1 Bb7 203. Rd1 Ba8 204. Kc2 Bb7 205. Kb1 Ba8 206. Ka2 Bb7 207. Ka3 Ba8 208. Ka4 Bb7 209. Ka5 Ba8 210. Kb6 h3 211. Ka5 Bb7 212. Ka4 Ba8 213. Ka3 Bb7 214. Ka2 Ba8 215. Kb1 Bb7 216. Kc2 Ba8 217. Kd3 Bb7 218. Rf1 Ba8 219. Re1 Bb7 220. Rd1 Ba8 221. Kc2 Bb7 222. Kb1 Ba8 223. Ka2 Bb7 224. Ka3 Ba8 225. Ka4 Bb7 226. Ka5 Ba8 227. Kb6 h1=Q 228. Rxh1 Bg7 229. Rd1+ Bd4 230. Ka5 Bb7 231. Ka4 Ba8 232. Ka3 Bb7 233. Ka2 Ba8 234. Kb1 Bb7 235. Kc2 Ba8 236. Kd3 Bb7 237. Rf1 Ba8 238. Re1 Bb7 239. Rd1 Ba8 240. Kc2 Bb7 241. Kb1 Ba8 242. Ka2 Bb7 243. Ka3 Ba8 244. Ka4 Bb7 245. Ka5 Ba8 246. Kb6 h2 247. Ka5 Bb7 248. Ka4 Ba8 249. Ka3 Bb7 250. Ka2 Ba8 251. Kb1 Bb7 252. Kc2 Ba8 253. Kd3 Bb7 254. Rf1 Ba8 255. Re1 Bb7 256. Rd1 Ba8 257. Kc2 Bb7 258. Kb1 Ba8 259. Ka2 Bb7 260. Ka3 Ba8 261. Ka4 Bb7 262. Ka5 Ba8 263. Kb6 h1=Q 264. Rxh1 Bg7 265. Rd1+ Bd4 266. Ka5 Bb7 267. Ka4 Ba8 268. Ka3 Bb7 269. Ka2 Ba8 270. Kb1 Bb7 271. Kc2 Ba8 272. Kd3 Bb7 273. Rf1 Ba8 274. Re1 Bb7 275. Rd1 Ba8 276. Kc2 Bb7 277. Kb1 Ba8 278. Ka2 Bb7 279. Ka3 Ba8 280. Ka4 Bb7 281. Ka5 Ba8 282. Kb6 Bb7 283. Kxb7 b1=Q 284. Rxb1 Be5 285. Rd1+ Bd4 286. Rxd4+ cxd4 287. Kb6 d3 288. a8=Q Rxb8+ 289. Qxb8 dxe2 290. Qxd8# 1-0
从棋盘
Pgn
结构体提供了Pgn::from_board
方法,用于使用Board
上的移动创建Pgn
对象。
use rschess::{Board, Pgn};
let mut board = Board::default();
for move_ in ["f3", "e5", "g4", "Qh4#"] {
board.make_move_san(move_).unwrap();
}
let pgn = Pgn::from_board(
board, // the board
vec![ // PGN tag pairs
("Event", "?"),
("Site", "?"),
("Date", "????.??.??"),
("Round", "?"),
("White", "?"),
("Black", "?"),
]
.into_iter()
.map(|(t, v)| (t.to_owned(), v.to_owned()))
.collect(),
)
.unwrap();
println!("{pgn}");
输出
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
[FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"]
1. f3 e5 2. g4 Qh4# 0-1
在这个例子中,PGN也必须遵循七个标签花名册,除了结果标签,因为这将根据Board
上游戏的状态来确定。
美化打印
以移动方为视角的格式化打印位置
use rschess::Board;
let board = Board::from_fen("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50".try_into().unwrap());
println!("{board}");
输出
1 | ♔ | | | | | | |
—————————————————————————————————
2 | ♙ | | ♛ | | | | | ♜
—————————————————————————————————
3 | | | ♙ | | | | |
—————————————————————————————————
4 | | | | ♙ | | | |
—————————————————————————————————
5 | ♙ | | ♖ | | | | |
—————————————————————————————————
6 | ♕ | | | | ♟ | | ♟ |
—————————————————————————————————
7 | ♚ | ♟ | ♟ | ♝ | | | |
—————————————————————————————————
8 | | | | | | ♖ | |
—————————————————————————————————
| h | g | f | e | d | c | d | a
以特定方为视角的格式化打印位置
use rschess::Color;
println!("{}", board.pretty_print(Color::White));
输出
8 | | | ♖ | | | | |
—————————————————————————————————
7 | | | | | ♝ | ♟ | ♟ | ♚
—————————————————————————————————
6 | | ♟ | | ♟ | | | | ♕
—————————————————————————————————
5 | | | | | | ♖ | | ♙
—————————————————————————————————
4 | | | | | ♙ | | |
—————————————————————————————————
3 | | | | | | ♙ | |
—————————————————————————————————
2 | ♜ | | | | | ♛ | | ♙
—————————————————————————————————
1 | | | | | | | | ♔
—————————————————————————————————
| a | b | c | d | e | f | g | h
位置到图像
use rschess::{Board, img};
let board = Board::from_fen("2R5/4bppk/1p1p3Q/5R1P/4P3/5P2/r4q1P/7K b - - 6 50".try_into().unwrap());
img::position_to_image(
board.position(), // the position
img::PositionImageProperties::default(), // image properties
board.side_to_move(), // perspective
)
.unwrap()
.save("Carlsen-Karjakin_WCC2016_R13_4.png")
.unwrap();
Carlsen-Karjakin_WCC2016_R13_4.png
图像属性
rschess 允许使用PositionImageProperties
结构体自定义由position_to_image
生成的图像。可以提供亮色方格和暗色方格的自定义颜色,并且还可以设置图像的大小。至于棋子集,rschess目前只有一个棋子集,即名为“normal”的Cburnett的SVG棋子:
历史
不久前,我想写一个简单的Rust程序来模拟象棋比赛。我之前使用过Python的chess库,知道如果Rust有一个类似的crate,我的任务将非常简单。但它没有。我很快就发现自己在Crates.io上浏览了数百个潜在选项,但找不到任何有用的东西。因此,我在Rust subreddit上提问,希望有人能告诉我一个没人听说过的强大crate。当然,没有哪个答案能帮我找到合适的crate,但u/LePfeiff的评论
听起来是一个很好的贡献机会;成为你想要看到的变化
让我深思。最初我有些犹豫,但在u/howtokillafox的鼓励下,rschess项目应运而生。
依赖项
~5–7MB
~134K SLoC