github.com/frankkopp/FrankyGo@v1.0.3/internal/movegen/perft_test.go (about) 1 // 2 // FrankyGo - UCI chess engine in GO for learning purposes 3 // 4 // MIT License 5 // 6 // Copyright (c) 2018-2020 Frank Kopp 7 // 8 // Permission is hereby granted, free of charge, to any person obtaining a copy 9 // of this software and associated documentation files (the "Software"), to deal 10 // in the Software without restriction, including without limitation the rights 11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 // copies of the Software, and to permit persons to whom the Software is 13 // furnished to do so, subject to the following conditions: 14 // 15 // The above copyright notice and this permission notice shall be included in all 16 // copies or substantial portions of the Software. 17 // 18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 // SOFTWARE. 25 // 26 27 package movegen 28 29 import ( 30 "testing" 31 32 "github.com/stretchr/testify/assert" 33 34 "github.com/frankkopp/FrankyGo/internal/position" 35 ) 36 37 // /////////////////////////////////////////////////////////////// 38 // Perft tests from https://www.chessprogramming.org/Perft_Results 39 // /////////////////////////////////////////////////////////////// 40 41 // Performing PERFT Test for Depth 6 42 // ----------------------------------------- 43 // Time : 24.895 ms 44 // NPS : 4.782.381 nps (from 4.486.000 without evasions) 45 // Results: 46 // Nodes : 119.060.324 47 // Captures : 2.812.008 48 // EnPassant : 5.248 49 // Checks : 809.099 50 // CheckMates: 10.828 51 // Castles : 0 52 // Promotions: 0 53 // ----------------------------------------- 54 // Finished PERFT Test for Depth 6 55 //noinspection GoImportUsedAsName 56 func TestStandardPerft(t *testing.T) { 57 58 maxDepth := 6 59 var perft Perft 60 assert := assert.New(t) 61 62 var results = [10][6]uint64{ 63 // @formatter:off 64 // N Nodes Captures EP Checks Mates 65 {0, 1, 0, 0, 0, 0}, 66 {1, 20, 0, 0, 0, 0}, 67 {2, 400, 0, 0, 0, 0}, 68 {3, 8_902, 34, 0, 12, 0}, 69 {4, 197_281, 1_576, 0, 469, 8}, 70 {5, 4_865_609, 82_719, 258, 27_351, 347}, 71 {6, 119_060_324, 2_812_008, 5_248, 809_099, 10_828}, 72 {7, 3_195_901_860, 108_329_926, 319_617, 33_103_848, 435_767}, 73 {8, 84_998_978_956, 3_523_740_106, 7_187_977, 968_981_593, 9_852_036}, 74 {9, 2_439_530_234_167, 125_208_536_153, 319_496_827, 36_095_901_903, 400_191_963}} 75 // @formatter:on 76 77 for i := 1; i <= maxDepth; i++ { 78 perft.StartPerft(position.StartFen, i, false) 79 assert.Equal(results[i][1], perft.Nodes) 80 assert.Equal(results[i][2], perft.CaptureCounter) 81 assert.Equal(results[i][3], perft.EnpassantCounter) 82 assert.Equal(results[i][4], perft.CheckCounter) 83 assert.Equal(results[i][5], perft.CheckMateCounter) 84 } 85 } 86 87 // Performing PERFT Test for Depth 6 88 // ----------------------------------------- 89 // Time : 24.368 ms 90 // NPS : 4.885.745 nps 91 // Results: 92 // Nodes : 119.060.324 93 // Captures : 2.812.008 94 // EnPassant : 5.248 95 // Checks : 809.099 96 // CheckMates: 10.828 97 // Castles : 0 98 // Promotions: 0 99 // ----------------------------------------- 100 // Finished PERFT Test for Depth 6 101 //noinspection GoImportUsedAsName 102 func TestStandardPerftOd(t *testing.T) { 103 104 maxDepth := 5 105 var perft Perft 106 assert := assert.New(t) 107 108 var results = [10][6]uint64{ 109 // @formatter:off 110 // N Nodes Captures EP Checks Mates 111 {0, 1, 0, 0, 0, 0}, 112 {1, 20, 0, 0, 0, 0}, 113 {2, 400, 0, 0, 0, 0}, 114 {3, 8_902, 34, 0, 12, 0}, 115 {4, 197_281, 1_576, 0, 469, 8}, 116 {5, 4_865_609, 82_719, 258, 27_351, 347}, 117 {6, 119_060_324, 2_812_008, 5_248, 809_099, 10_828}, 118 {7, 3_195_901_860, 108_329_926, 319_617, 33_103_848, 435_767}, 119 {8, 84_998_978_956, 3_523_740_106, 7_187_977, 968_981_593, 9_852_036}, 120 {9, 2_439_530_234_167, 125_208_536_153, 319_496_827, 36_095_901_903, 400_191_963}} 121 // @formatter:on 122 123 for i := 1; i <= maxDepth; i++ { 124 perft.StartPerft(position.StartFen, i, true) 125 assert.Equal(results[i][1], perft.Nodes) 126 assert.Equal(results[i][2], perft.CaptureCounter) 127 assert.Equal(results[i][3], perft.EnpassantCounter) 128 assert.Equal(results[i][4], perft.CheckCounter) 129 assert.Equal(results[i][5], perft.CheckMateCounter) 130 } 131 } 132 133 // Performing PERFT Test for Depth 6 134 // FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 135 // ----------------------------------------- 136 // Time : 28m54.8687383s 137 // NPS : 4.629.541 nps 138 // Results: 139 // Nodes : 8.031.647.685 140 // Captures : 1.558.445.089 141 // EnPassant : 3.577.504 142 // Checks : 92.238.050 143 // CheckMates: 360.003 144 // Castles : 184.513.607 145 // Promotions: 56.627.920 146 // ----------------------------------------- 147 // Finished PERFT Test for Depth 6 148 //noinspection GoImportUsedAsName 149 func TestKiwipetePerft(t *testing.T) { 150 151 maxDepth := 4 152 var perft Perft 153 assert := assert.New(t) 154 155 var kiwipete = [10][8]uint64{ 156 // @formatter:off 157 // N Nodes Captures EP Checks Mates Castles Promotions 158 {0, 1, 0, 0, 0, 0, 0, 0}, 159 {1, 48, 8, 0, 0, 0, 2, 0}, 160 {2, 2_039, 351, 1, 3, 0, 91, 0}, 161 {3, 97_862, 17_102, 45, 993, 1, 3_162, 0}, 162 {4, 4_085_603, 757_163, 1_929, 25_523, 43, 128_013, 15_172}, 163 {5, 193_690_690, 35_043_416, 73_365, 3_309_887, 30_171, 4_993_637, 8_392}, 164 {6, 8_031_647_685, 1_558_445_089, 3_577_504, 92_238_050, 360_003, 184_513_607, 56_627_920}} 165 166 for depth := 1; depth <= maxDepth; depth++ { 167 perft.StartPerft("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - ", depth, true) 168 assert.Equal(kiwipete[depth][1], perft.Nodes) 169 assert.Equal(kiwipete[depth][2], perft.CaptureCounter) 170 assert.Equal(kiwipete[depth][3], perft.EnpassantCounter) 171 assert.Equal(kiwipete[depth][4], perft.CheckCounter) 172 assert.Equal(kiwipete[depth][5], perft.CheckMateCounter) 173 assert.Equal(kiwipete[depth][6], perft.CastleCounter) 174 assert.Equal(kiwipete[depth][7], perft.PromotionCounter) 175 } 176 } 177 178 //noinspection GoImportUsedAsName 179 func TestMirrorPerft(t *testing.T) { 180 181 maxDepth := 5 182 var perft Perft 183 assert := assert.New(t) 184 185 var mirrorPerft = [10][8]uint64{ 186 // @formatter:off 187 // N Nodes Captures EP Checks Mates Castles Promotions 188 {0, 1, 0, 0, 0, 0, 0, 0}, 189 {1, 6, 0, 0, 0, 0, 0, 0}, 190 {2, 264, 87, 0, 10, 0, 6, 48}, 191 {3, 9467, 1021, 4, 38, 22, 0, 120}, 192 {4, 422333, 131393, 0, 15492, 5, 7795, 60032}, 193 {5, 15833292, 2046173, 6512, 200568, 50562, 0, 329464}, 194 {6, 706045033, 210369132, 212, 26973664, 81076, 10882006, 81102984}} 195 196 // white 197 for depth := 1; depth <= maxDepth; depth++ { 198 perft.StartPerft("r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq -", depth, false) 199 assert.Equal(mirrorPerft[depth][1], perft.Nodes) 200 assert.Equal(mirrorPerft[depth][2], perft.CaptureCounter) 201 assert.Equal(mirrorPerft[depth][3], perft.EnpassantCounter) 202 assert.Equal(mirrorPerft[depth][4], perft.CheckCounter) 203 assert.Equal(mirrorPerft[depth][5], perft.CheckMateCounter) 204 assert.Equal(mirrorPerft[depth][6], perft.CastleCounter) 205 assert.Equal(mirrorPerft[depth][7], perft.PromotionCounter) 206 } 207 208 // mirrored 209 for depth := 1; depth <= maxDepth; depth++ { 210 perft.StartPerft("r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ -", depth, false) 211 assert.Equal(mirrorPerft[depth][1], perft.Nodes) 212 assert.Equal(mirrorPerft[depth][2], perft.CaptureCounter) 213 assert.Equal(mirrorPerft[depth][3], perft.EnpassantCounter) 214 assert.Equal(mirrorPerft[depth][4], perft.CheckCounter) 215 assert.Equal(mirrorPerft[depth][5], perft.CheckMateCounter) 216 assert.Equal(mirrorPerft[depth][6], perft.CastleCounter) 217 assert.Equal(mirrorPerft[depth][7], perft.PromotionCounter) 218 } 219 } 220 221 //noinspection GoImportUsedAsName 222 func TestPos5Perft(t *testing.T) { 223 224 maxDepth := 4 225 var perft Perft 226 assert := assert.New(t) 227 228 var kiwipete = [10][2]uint64{ 229 // @formatter:off 230 // N Nodes 231 {0, 1}, 232 {1, 44}, 233 {2, 1_486}, 234 {3, 62_379}, 235 {4, 2_103_487}, 236 {5, 89_941_194}} 237 238 for depth := 1; depth <= maxDepth; depth++ { 239 perft.StartPerft("rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ -", depth, false) 240 assert.Equal(kiwipete[depth][1], perft.Nodes) 241 } 242 }