test.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /**
  2. Tests for smallchesslib. These are basic tests that should be run before
  3. every commit, just to catch major regressions.
  4. by drummyfish, released under CC0 1.0
  5. */
  6. void putCharacter(char c)
  7. {
  8. putchar(c);
  9. }
  10. char str[4096];
  11. void putCharStr(char c)
  12. {
  13. char *s = str;
  14. while (*s != 0)
  15. s++;
  16. *s = c;
  17. *(s + 1) = 0;
  18. }
  19. #include <stdio.h>
  20. #include "smallchesslib.h"
  21. uint8_t test(const char *str, uint8_t cond)
  22. {
  23. printf("- testing %s: ",str);
  24. if (cond)
  25. {
  26. puts("OK");
  27. return 1;
  28. }
  29. puts("ERROR");
  30. return 0;
  31. }
  32. int strEquals(const char *s1, const char *s2)
  33. {
  34. while (1)
  35. {
  36. if (*s1 != *s2)
  37. return 0;
  38. if (*s1 == 0 || *s2 == 0)
  39. break;
  40. s1++;
  41. s2++;
  42. }
  43. return 1;
  44. }
  45. int main(void)
  46. {
  47. #define assert(str,cond) if (!test(str,cond)) return 1;
  48. SCL_SquareSet emptySquareSet = SCL_SQUARE_SET_EMPTY;
  49. {
  50. SCL_Board board = SCL_BOARD_START_STATE;
  51. assert("square color",SCL_squareIsWhite(SCL_stringToSquare("H1")))
  52. assert("square color",!SCL_squareIsWhite(SCL_stringToSquare("d4")))
  53. assert("piece color",SCL_pieceIsWhite('K'))
  54. assert("piece color",!SCL_pieceIsWhite('p'))
  55. assert("piece to color",SCL_pieceToColor('q',1) == 'Q')
  56. assert("piece to color",SCL_pieceToColor('R',1) == 'R')
  57. assert("piece to color",SCL_pieceToColor('p',0) == 'p')
  58. assert("piece to color",SCL_pieceToColor('K',0) == 'k')
  59. assert("square number", SCL_SQUARE('d',4) == SCL_stringToSquare("D4"))
  60. assert("square number", SCL_SQUARE('h',8) == SCL_stringToSquare("h8"))
  61. uint8_t s0, s1, r;
  62. char p;
  63. r = SCL_stringToMove("e2e4",&s0,&s1,&p);
  64. assert("string to move",s0 == SCL_S('e',2) && s1 == SCL_S('e',4) && r);
  65. r = SCL_stringToMove("H7G8q ",&s0,&s1,&p);
  66. assert("string to move",s0 == SCL_S('h',7) && s1 == SCL_S('g',8) && r && p == 'q');
  67. r = SCL_stringToMove("ie3!",&s0,&s1,&p);
  68. assert("illegal string to move",!r);
  69. puts("testing not crashing");
  70. r = SCL_stringToMove("aq",&s0,&s1,&p);
  71. SCL_boardInit960(board,950);
  72. assert("960",SCL_boardHash32(board) == 866912113);
  73. SCL_boardInit960(board,300);
  74. assert("960",SCL_boardHash32(board) == 3028682732);
  75. }
  76. {
  77. SCL_SquareSet s = SCL_SQUARE_SET_EMPTY;
  78. assert("empty square set",
  79. !SCL_squareSetContains(s,0) &&
  80. !SCL_squareSetContains(s,63) &&
  81. !SCL_squareSetContains(s,SCL_stringToSquare("c4")))
  82. SCL_squareSetAdd(s,SCL_stringToSquare("c4"));
  83. assert("square set contains",SCL_squareSetContains(s,SCL_stringToSquare("c4")))
  84. }
  85. {
  86. SCL_Board board = SCL_BOARD_START_STATE;
  87. puts("placing pieces");
  88. SCL_boardSetPosition(board,
  89. "r......."
  90. "p....p.p"
  91. ".p..pnpb"
  92. "n.p.P..."
  93. "B....qbP"
  94. "PkNQ...."
  95. ".PP..rPR"
  96. "R...KBN.",255,0,0);
  97. SCL_printBoard(board,putCharacter,emptySquareSet,255,SCL_PRINT_FORMAT_UTF8,4,1,0);
  98. assert("not check",!SCL_boardCheck(board,1));
  99. assert("check",SCL_boardCheck(board,0));
  100. assert("square not attacked",!SCL_boardSquareAttacked(board,SCL_stringToSquare("A8"),0));
  101. assert("square not attacked",!SCL_boardSquareAttacked(board,SCL_stringToSquare("H4"),1));
  102. assert("square attacked",SCL_boardSquareAttacked(board,SCL_stringToSquare("H8"),1));
  103. assert("square attacked",SCL_boardSquareAttacked(board,SCL_stringToSquare("G1"),0));
  104. puts("placing pieces");
  105. SCL_boardSetPosition(board,
  106. "R...K..R"
  107. ".p....PP"
  108. ".n......"
  109. "b...Q..."
  110. "........"
  111. "..P...p."
  112. "........"
  113. "r...k..r",255,0,1);
  114. SCL_printBoard(board,putCharacter,emptySquareSet,255,SCL_PRINT_FORMAT_UTF8,4,1,0);
  115. assert("check position",SCL_boardGetPosition(board) == SCL_POSITION_CHECK);
  116. SCL_SquareSet set;
  117. SCL_boardGetPseudoMoves(board,4,1,set);
  118. assert("king moves (castling)",SCL_squareSetSize(set) == 7);
  119. SCL_boardGetPseudoMoves(board,60,1,set);
  120. assert("king moves (castling)",SCL_squareSetSize(set) == 5);
  121. SCL_boardMakeMove(board,9,1,'q');
  122. assert("promotion",board[9] == '.' && board[1] == 'q');
  123. SCL_boardSetPosition(board,
  124. "........"
  125. "........"
  126. "........"
  127. "PpP....."
  128. ".....Pp."
  129. "........"
  130. "........"
  131. "........",255,0,0);
  132. board[SCL_BOARD_ENPASSANT_CASTLE_BYTE] = (char) 0xf6;
  133. SCL_boardGetPseudoMoves(board,37,1,set);
  134. assert("en-passant",SCL_squareSetSize(set) == 2);
  135. SCL_boardGetPseudoMoves(board,25,1,set);
  136. assert("en-passant",SCL_squareSetSize(set) == 1);
  137. }
  138. {
  139. SCL_Board board = SCL_BOARD_START_STATE;
  140. uint32_t hash = SCL_boardHash32(board);
  141. SCL_boardFromFEN(board,"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
  142. assert("board from FEN (start position)",hash == SCL_boardHash32(board));
  143. SCL_boardFromFEN(board,"1nbqkb1r/pp5p/2p3pn/1r3p2/N2PPQ2/1Q5N/PP2BPPP/R1B2RK1 b k - 0 1");
  144. assert("board from FEN",SCL_boardHash32(board) == 2308982684);
  145. assert("board from FEN (bad FEN)",SCL_boardFromFEN(board,"1nbqkb1r/pp5p/2p3pn/1r3p2/N2PPQ2/1Q5N/PP2BPPP/R1B2RK1 b k - 0") == 0);
  146. assert("board from FEN (bad FEN)",SCL_boardFromFEN(board,"1nb ass LLsasa LL221") == 0);
  147. }
  148. {
  149. SCL_Record r;
  150. SCL_recordInit(r);
  151. assert("record empty",SCL_recordLength(r) == 0);
  152. SCL_recordAdd(r,SCL_SQUARE('e',2),SCL_SQUARE('e',4),'q',SCL_RECORD_CONT);
  153. assert("record length = 1",SCL_recordLength(r) == 1);
  154. SCL_recordRemoveLast(r);
  155. SCL_recordRemoveLast(r);
  156. assert("record empty",SCL_recordLength(r) == 0);
  157. SCL_recordAdd(r,SCL_SQUARE('f',2),SCL_SQUARE('f',4),'q',SCL_RECORD_CONT);
  158. SCL_recordAdd(r,SCL_SQUARE('f',7),SCL_SQUARE('f',5),'r',SCL_RECORD_CONT);
  159. SCL_recordAdd(r,SCL_SQUARE('g',1),SCL_SQUARE('f',3),'q',SCL_RECORD_CONT);
  160. assert("record length = 3",SCL_recordLength(r) == 3);
  161. uint8_t s0, s1, e;
  162. char p;
  163. e = SCL_recordGetMove(r,1,&s0,&s1,&p);
  164. assert("record check move 1",
  165. (s0 == SCL_stringToSquare("f7")) &&
  166. (s1 == SCL_stringToSquare("f5")) &&
  167. (p == 'r') && (e == SCL_RECORD_CONT));
  168. e = SCL_recordGetMove(r,2,&s0,&s1,&p);
  169. assert("record check move 2",
  170. (s0 == SCL_stringToSquare("g1")) &&
  171. (s1 == SCL_stringToSquare("f3")) &&
  172. (p == 'q') && (e == SCL_RECORD_END));
  173. SCL_recordAdd(r,SCL_SQUARE('b',8),SCL_SQUARE('b',6),'q',SCL_RECORD_CONT);
  174. SCL_recordAdd(r,SCL_SQUARE('g',2),SCL_SQUARE('g',4),'q',SCL_RECORD_CONT);
  175. SCL_recordAdd(r,SCL_SQUARE('f',5),SCL_SQUARE('g',4),'q',SCL_RECORD_CONT);
  176. SCL_recordAdd(r,SCL_SQUARE('f',1),SCL_SQUARE('h',3),'q',SCL_RECORD_CONT);
  177. SCL_recordAdd(r,SCL_SQUARE('e',7),SCL_SQUARE('e',5),'q',SCL_RECORD_CONT);
  178. SCL_recordAdd(r,SCL_SQUARE('e',1),SCL_SQUARE('g',1),'q',SCL_RECORD_CONT);
  179. SCL_Board board = SCL_BOARD_START_STATE;
  180. SCL_recordApply(r,board,100);
  181. SCL_Board board2;
  182. SCL_boardSetPosition(board2,
  183. "RNBQ.RK."
  184. "PPPPP..P"
  185. ".....N.B"
  186. ".....Pp."
  187. "....p..."
  188. ".n......"
  189. "pppp..pp"
  190. "r.bqkbnr",207,1,9);
  191. SCL_SquareSet s = SCL_SQUARE_SET_EMPTY;
  192. assert("replaying record",!SCL_boardsDiffer(board,board2));
  193. SCL_printBoard(board,putCharacter,s,255,SCL_PRINT_FORMAT_UTF8,4,1,0);
  194. assert("normal position",SCL_boardGetPosition(board) == SCL_POSITION_NORMAL);
  195. }
  196. {
  197. SCL_Record r;
  198. SCL_recordInit(r);
  199. SCL_recordAdd(r,SCL_SQUARE('h',2),SCL_SQUARE('h',4),'q',SCL_RECORD_CONT);
  200. SCL_recordAdd(r,SCL_SQUARE('g',7),SCL_SQUARE('g',5),'q',SCL_RECORD_CONT);
  201. SCL_recordAdd(r,SCL_SQUARE('h',4),SCL_SQUARE('g',5),'q',SCL_RECORD_CONT);
  202. SCL_recordAdd(r,SCL_SQUARE('g',8),SCL_SQUARE('f',6),'q',SCL_RECORD_CONT);
  203. SCL_recordAdd(r,SCL_SQUARE('g',1),SCL_SQUARE('f',3),'q',SCL_RECORD_CONT);
  204. SCL_recordAdd(r,SCL_SQUARE('f',8),SCL_SQUARE('g',7),'q',SCL_RECORD_CONT);
  205. SCL_recordAdd(r,SCL_SQUARE('e',2),SCL_SQUARE('e',3),'q',SCL_RECORD_CONT);
  206. SCL_recordAdd(r,SCL_SQUARE('e',8),SCL_SQUARE('g',8),'q',SCL_RECORD_CONT);
  207. SCL_recordAdd(r,SCL_SQUARE('b',1),SCL_SQUARE('c',3),'q',SCL_RECORD_CONT);
  208. SCL_recordAdd(r,SCL_SQUARE('c',7),SCL_SQUARE('c',5),'q',SCL_RECORD_CONT);
  209. SCL_recordAdd(r,SCL_SQUARE('d',2),SCL_SQUARE('d',3),'q',SCL_RECORD_CONT);
  210. SCL_recordAdd(r,SCL_SQUARE('c',5),SCL_SQUARE('c',4),'q',SCL_RECORD_CONT);
  211. SCL_recordAdd(r,SCL_SQUARE('b',2),SCL_SQUARE('b',4),'q',SCL_RECORD_CONT);
  212. SCL_recordAdd(r,SCL_SQUARE('c',4),SCL_SQUARE('b',3),'q',SCL_RECORD_CONT);
  213. SCL_recordAdd(r,SCL_SQUARE('c',1),SCL_SQUARE('a',3),'q',SCL_RECORD_CONT);
  214. SCL_recordAdd(r,SCL_SQUARE('d',8),SCL_SQUARE('c',7),'q',SCL_RECORD_CONT);
  215. SCL_recordAdd(r,SCL_SQUARE('d',1),SCL_SQUARE('d',2),'q',SCL_RECORD_CONT);
  216. SCL_recordAdd(r,SCL_SQUARE('b',8),SCL_SQUARE('c',6),'q',SCL_RECORD_CONT);
  217. SCL_recordAdd(r,SCL_SQUARE('e',1),SCL_SQUARE('c',1),'q',SCL_RECORD_CONT);
  218. SCL_recordAdd(r,SCL_SQUARE('f',6),SCL_SQUARE('d',5),'q',SCL_RECORD_CONT);
  219. SCL_recordAdd(r,SCL_SQUARE('c',2),SCL_SQUARE('b',3),'q',SCL_RECORD_CONT);
  220. SCL_recordAdd(r,SCL_SQUARE('c',6),SCL_SQUARE('b',4),'q',SCL_RECORD_CONT);
  221. SCL_recordAdd(r,SCL_SQUARE('g',5),SCL_SQUARE('g',6),'q',SCL_RECORD_CONT);
  222. SCL_recordAdd(r,SCL_SQUARE('c',7),SCL_SQUARE('c',3),'q',SCL_RECORD_CONT);
  223. SCL_recordAdd(r,SCL_SQUARE('d',2),SCL_SQUARE('c',2),'q',SCL_RECORD_CONT);
  224. SCL_recordAdd(r,SCL_SQUARE('d',7),SCL_SQUARE('d',6),'q',SCL_RECORD_CONT);
  225. SCL_recordAdd(r,SCL_SQUARE('g',6),SCL_SQUARE('h',7),'q',SCL_RECORD_CONT);
  226. SCL_recordAdd(r,SCL_SQUARE('g',8),SCL_SQUARE('h',8),'q',SCL_RECORD_CONT);
  227. SCL_recordAdd(r,SCL_SQUARE('c',2),SCL_SQUARE('c',3),'q',SCL_RECORD_CONT);
  228. SCL_recordAdd(r,SCL_SQUARE('g',7),SCL_SQUARE('c',3),'q',SCL_RECORD_CONT);
  229. SCL_recordAdd(r,SCL_SQUARE('a',3),SCL_SQUARE('b',4),'q',SCL_RECORD_CONT);
  230. SCL_recordAdd(r,SCL_SQUARE('h',8),SCL_SQUARE('g',7),'q',SCL_RECORD_CONT);
  231. SCL_recordAdd(r,SCL_SQUARE('h',7),SCL_SQUARE('h',8),'r',SCL_RECORD_CONT);
  232. SCL_recordAdd(r,SCL_SQUARE('d',5),SCL_SQUARE('b',4),'r',SCL_RECORD_CONT);
  233. SCL_recordAdd(r,SCL_SQUARE('f',1),SCL_SQUARE('e',2),'r',SCL_RECORD_CONT);
  234. SCL_recordAdd(r,SCL_SQUARE('g',7),SCL_SQUARE('f',6),'r',SCL_RECORD_CONT);
  235. SCL_recordAdd(r,SCL_SQUARE('h',1),SCL_SQUARE('f',1),'r',SCL_RECORD_CONT);
  236. SCL_recordAdd(r,SCL_SQUARE('f',6),SCL_SQUARE('g',7),'r',SCL_RECORD_CONT);
  237. SCL_recordAdd(r,SCL_SQUARE('f',1),SCL_SQUARE('h',1),'r',SCL_RECORD_CONT);
  238. SCL_recordAdd(r,SCL_SQUARE('b',4),SCL_SQUARE('a',6),'r',SCL_RECORD_CONT);
  239. SCL_recordAdd(r,SCL_SQUARE('h',1),SCL_SQUARE('h',4),'r',SCL_RECORD_CONT);
  240. str[0] = 0;
  241. SCL_printPGN(r,putCharStr,0);
  242. assert("to PGN",strEquals(str,
  243. "1. h4 g5 2. hxg5 Nf6 3. Nf3 Bg7 4. e3 O-O 5. Nc3 c5 6. d3 c4 7. b4 cxb3 8. Ba3 Qc7 9. Qd2 Nc6 10. O-O-O Nd5 11. cxb3 Ncb4 12. g6 Qxc3+ 13. Qc2 d6 14. gxh7+ Kh8 15. Qxc3 Bxc3 16. Bxb4 Kg7 17. h8=R Nxb4 18. Be2 Kf6 19. Rhf1 Kg7 20. Rfh1 Na6 21. R1h4*"));
  244. SCL_Board board = SCL_BOARD_START_STATE;
  245. SCL_recordApply(r,board,100);
  246. uint32_t hash = SCL_boardHash32(board);
  247. SCL_recordInit(r);
  248. SCL_recordFromPGN(r,str);
  249. SCL_boardInit(board);
  250. SCL_recordApply(r,board,100);
  251. assert("from PGN",hash == SCL_boardHash32(board));
  252. }
  253. {
  254. puts("testing positions");
  255. SCL_Board board = SCL_BOARD_START_STATE;
  256. assert("position = normal",SCL_boardGetPosition(board) == SCL_POSITION_NORMAL);
  257. assert("value = 0",SCL_boardEvaluateStatic(board) == 0);
  258. SCL_boardSetPosition(board,
  259. "rnbq.rk."
  260. "ppppp..p"
  261. ".......b"
  262. "........"
  263. "..B....."
  264. ".N......"
  265. "PPPP..PP"
  266. "R..QKBNR",255,0,3);
  267. assert("position = check",SCL_boardGetPosition(board) == SCL_POSITION_CHECK);
  268. SCL_boardSetPosition(board,
  269. "rnb....q"
  270. "pppppQkp"
  271. ".......b"
  272. "........"
  273. "..B....."
  274. ".N......"
  275. "PPPP..PP"
  276. "R...KBNR",255,0,5);
  277. assert("position = mate",SCL_boardGetPosition(board) == SCL_POSITION_MATE);
  278. SCL_boardSetPosition(board,
  279. "k......."
  280. ".......R"
  281. "........"
  282. "........"
  283. "........"
  284. "........"
  285. "........"
  286. ".R...K..",255,0,1);
  287. assert("position = stalemate",SCL_boardGetPosition(board) == SCL_POSITION_STALEMATE);
  288. assert("value == 0",SCL_boardEvaluateStatic(board) == 0);
  289. SCL_boardSetPosition(board,
  290. "...B...."
  291. "......k."
  292. "........"
  293. "........"
  294. "K......."
  295. "........"
  296. ".....b.."
  297. "........",255,0,0);
  298. assert("position = dead",SCL_boardGetPosition(board) == SCL_POSITION_DEAD);
  299. assert("value = 0",SCL_boardEvaluateStatic(board) == 0);
  300. SCL_boardSetPosition(board,
  301. "....k..."
  302. "........"
  303. "........"
  304. "........"
  305. "........"
  306. "........"
  307. "..R...R."
  308. "....K...",255,0,0);
  309. assert("position = normal",SCL_boardGetPosition(board) == SCL_POSITION_NORMAL);
  310. assert("value != 0",SCL_boardEvaluateStatic(board) != 0);
  311. SCL_boardSetPosition(board,
  312. "rn.qkbnr"
  313. "pp..pppp"
  314. "..p....."
  315. "...p...."
  316. "........"
  317. "...P...."
  318. "PPP.PP.P"
  319. "R.BQKB.R",255,0,0);
  320. assert("position = normal",SCL_boardGetPosition(board) == SCL_POSITION_NORMAL);
  321. SCL_boardSetPosition(board,
  322. "........"
  323. "PPP..PPP"
  324. "k......."
  325. "...PP..."
  326. "........"
  327. "........"
  328. "........"
  329. "RNBQKBNR",255,0,5);
  330. assert("position = check",SCL_boardGetPosition(board) == SCL_POSITION_CHECK);
  331. }
  332. {
  333. puts("testing undos ");
  334. SCL_MoveUndo undos[1024];
  335. uint8_t undoCount = 0;
  336. SCL_Board board = SCL_BOARD_START_STATE;
  337. #define m(f,t)\
  338. undos[undoCount] = SCL_boardMakeMove(board,f,t,'q');\
  339. undoCount++;
  340. m(SCL_SQUARE('e',2),SCL_SQUARE('e',4))
  341. m(SCL_SQUARE('d',7),SCL_SQUARE('d',5))
  342. m(SCL_SQUARE('e',4),SCL_SQUARE('d',5))
  343. m(SCL_SQUARE('b',8),SCL_SQUARE('c',6))
  344. m(SCL_SQUARE('d',1),SCL_SQUARE('f',3))
  345. m(SCL_SQUARE('c',8),SCL_SQUARE('g',4))
  346. m(SCL_SQUARE('f',1),SCL_SQUARE('d',3))
  347. m(SCL_SQUARE('e',7),SCL_SQUARE('e',5))
  348. m(SCL_SQUARE('d',5),SCL_SQUARE('e',6))
  349. m(SCL_SQUARE('d',8),SCL_SQUARE('d',3))
  350. m(SCL_SQUARE('g',1),SCL_SQUARE('e',2))
  351. m(SCL_SQUARE('e',8),SCL_SQUARE('c',8))
  352. m(SCL_SQUARE('e',1),SCL_SQUARE('g',1))
  353. m(SCL_SQUARE('b',7),SCL_SQUARE('b',5))
  354. m(SCL_SQUARE('f',3),SCL_SQUARE('f',7))
  355. m(SCL_SQUARE('b',5),SCL_SQUARE('b',4))
  356. m(SCL_SQUARE('e',6),SCL_SQUARE('e',7))
  357. m(SCL_SQUARE('b',4),SCL_SQUARE('b',3))
  358. m(SCL_SQUARE('e',7),SCL_SQUARE('f',8))
  359. m(SCL_SQUARE('b',3),SCL_SQUARE('c',2))
  360. m(SCL_SQUARE('g',1),SCL_SQUARE('h',1))
  361. undos[undoCount] = SCL_boardMakeMove(board,
  362. SCL_SQUARE('c',2),
  363. SCL_SQUARE('b',1),'n');
  364. undoCount++;
  365. m(SCL_SQUARE('f',8),SCL_SQUARE('d',8))
  366. m(SCL_SQUARE('c',8),SCL_SQUARE('b',7))
  367. m(SCL_SQUARE('f',7),SCL_SQUARE('g',8))
  368. m(SCL_SQUARE('h',7),SCL_SQUARE('h',5))
  369. m(SCL_SQUARE('b',2),SCL_SQUARE('b',3))
  370. m(SCL_SQUARE('g',4),SCL_SQUARE('f',5))
  371. m(SCL_SQUARE('d',8),SCL_SQUARE('d',3))
  372. m(SCL_SQUARE('h',5),SCL_SQUARE('h',4))
  373. m(SCL_SQUARE('g',2),SCL_SQUARE('g',4))
  374. m(SCL_SQUARE('h',4),SCL_SQUARE('g',3))
  375. m(SCL_SQUARE('a',1),SCL_SQUARE('b',1))
  376. m(SCL_SQUARE('g',3),SCL_SQUARE('f',2))
  377. m(SCL_SQUARE('f',1),SCL_SQUARE('d',1))
  378. undos[undoCount] = SCL_boardMakeMove(board,
  379. SCL_SQUARE('f',2),
  380. SCL_SQUARE('f',1),'r');
  381. undoCount++;
  382. #undef m
  383. while (undoCount > 0)
  384. {
  385. undoCount--;
  386. SCL_boardUndoMove(board,undos[undoCount]);
  387. }
  388. SCL_Board board2 = SCL_BOARD_START_STATE;
  389. for (int i = 0; i < SCL_BOARD_STATE_SIZE; ++i)
  390. if (board[i] != board2[i])
  391. {
  392. puts("ERROR");
  393. return 0;
  394. }
  395. puts("OK");
  396. }
  397. {
  398. puts("testing AI");
  399. uint8_t s0, s1;
  400. char p;
  401. SCL_Board board = SCL_BOARD_START_STATE;
  402. SCL_SquareSet s = SCL_SQUARE_SET_EMPTY;
  403. SCL_randomSimpleSeed(40);
  404. printf("does AI make legal moves? ");
  405. for (uint16_t i = 0; i < 500; ++i)
  406. {
  407. if (SCL_boardGameOver(board))
  408. break;
  409. uint8_t depth = SCL_boardWhitesTurn(board) ? 2 : 0;
  410. SCL_getAIMove(board,depth,1,1,SCL_boardEvaluateStatic,SCL_randomSimple,2,
  411. 0,0,&s0,&s1,&p);
  412. if (board[s0] == '.' || s0 == s1)
  413. {
  414. printf("ERROR: AI made an illegal move\n");
  415. SCL_printBoard(board,putCharacter,s,s0,SCL_PRINT_FORMAT_UTF8,4,1,0);
  416. return 1;
  417. }
  418. SCL_boardMakeMove(board,s0,s1,p);
  419. }
  420. puts("OK");
  421. printf("Does AI win against random moves? ");
  422. if (!(SCL_boardMate(board) && !SCL_boardWhitesTurn(board)))
  423. {
  424. printf("ERROR: AI didn't win against random moves\n");
  425. return 1;
  426. }
  427. puts("OK");
  428. /* this checks if the AI behavior changed against previous version, change
  429. the hash if the change was intentional */
  430. assert("AI behavior didn't change?",SCL_boardHash32(board) == 1629239492);
  431. SCL_boardFromFEN(board,"7R/8/8/1Q6/8/8/k7/3K4 w - - 0 1");
  432. printf("mate in 1 (white): ");
  433. SCL_getAIMove(board,2,3,1,SCL_boardEvaluateStatic,0,0,0,0,
  434. &s0,&s1,&p);
  435. if ((s0 != 63) || (s1 != 56))
  436. {
  437. puts("ERROR");
  438. return 1;
  439. }
  440. puts("OK");
  441. SCL_boardFromFEN(board,"8/5N2/8/1r5k/5q2/8/8/K7 b - - 0 1");
  442. printf("mate in 1 (black): ");
  443. SCL_getAIMove(board,2,3,1,SCL_boardEvaluateStatic,0,0,0,0,
  444. &s0,&s1,&p);
  445. if ((s0 != 29) || (s1 != 24))
  446. {
  447. puts("ERROR");
  448. return 1;
  449. }
  450. puts("OK");
  451. SCL_boardFromFEN(board,"1k2r3/8/8/7B/8/8/2N1N1N1/1K6 w - - 0 1");
  452. SCL_getAIMove(board,2,3,1,SCL_boardEvaluateStatic,0,0,0,0,
  453. &s0,&s1,&p);
  454. assert("makes a good move?",s0 == 39 && s1 == 60);
  455. SCL_getAIMove(board,2,3,1,SCL_boardEvaluateStatic,0,0,39,60,
  456. &s0,&s1,&p);
  457. assert("avoids draw?",s0 != 39 || s1 != 60);
  458. }
  459. {
  460. puts("testing game struct");
  461. SCL_Game game;
  462. SCL_gameInit(&game,0);
  463. SCL_gameMakeMove(&game,1,18,'q');
  464. SCL_gameMakeMove(&game,57,40,'q');
  465. SCL_gameMakeMove(&game,18,1,'q');
  466. SCL_gameMakeMove(&game,40,57,'q');
  467. SCL_gameMakeMove(&game,1,18,'q');
  468. SCL_gameMakeMove(&game,57,40,'q');
  469. SCL_gameMakeMove(&game,18,1,'q');
  470. assert("game state == playing?",game.state == SCL_GAME_STATE_PLAYING);
  471. SCL_gameUndoMove(&game);
  472. SCL_gameMakeMove(&game,18,1,'q');
  473. SCL_gameMakeMove(&game,40,57,'q');
  474. assert("repetition draw?",game.state == SCL_GAME_STATE_DRAW_REPETITION);
  475. }
  476. return 0;
  477. #undef assert
  478. }