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  }