diff --git a/source/movegen.cpp b/source/movegen.cpp index dca7ff589..c1d25305a 100644 --- a/source/movegen.cpp +++ b/source/movegen.cpp @@ -909,8 +909,8 @@ ExtMove* generateMoves(const Position& pos, ExtMove* mlist, Square recapSq) // 歩の不成などを含め、すべての指し手を生成するのか。 // GenTypeの末尾に"ALL"とついているものがその対象。 const bool All = (GenType == EVASIONS_ALL) || (GenType == CHECKS_ALL) || (GenType == LEGAL_ALL) - || (GenType == NON_EVASIONS_ALL) || (GenType == RECAPTURES_ALL) || (GenType == QUIET_CHECKS_ALL); - //|| (GenType == CAPTURES_PRO_PLUS_ALL) || (GenType == NON_CAPTURES_PRO_MINUS_ALL); + || (GenType == NON_EVASIONS_ALL) || (GenType == RECAPTURES_ALL) || (GenType == QUIET_CHECKS_ALL) + || (GenType == CAPTURES_PRO_PLUS_ALL) || (GenType == NON_CAPTURES_PRO_MINUS_ALL); if (GenType == LEGAL || GenType == LEGAL_ALL) { @@ -956,11 +956,11 @@ ExtMove* generateMoves(const Position& pos, ExtMove* mlist, Square recapSq) // ただし、NON_EVASIONS_ALL , RECAPTURES_ALLは、ALLではないほうを呼び出す必要がある。 // EVASIONS_ALLは上で呼び出されているが、実際はここでも実体化されたあと、最適化によって削除されるので、ここでも書く必要がある。 const auto GenType2 = - GenType == NON_EVASIONS_ALL ? NON_EVASIONS : - GenType == RECAPTURES_ALL ? RECAPTURES : - GenType == EVASIONS_ALL ? EVASIONS : - //GenType == CAPTURES_PRO_PLUS_ALL ? CAPTURES_PRO_PLUS : - //GenType == NON_CAPTURES_PRO_MINUS_ALL ? NON_CAPTURES_PRO_MINUS : + GenType == NON_EVASIONS_ALL ? NON_EVASIONS : + GenType == RECAPTURES_ALL ? RECAPTURES : + GenType == EVASIONS_ALL ? EVASIONS : + GenType == CAPTURES_PRO_PLUS_ALL ? CAPTURES_PRO_PLUS : + GenType == NON_CAPTURES_PRO_MINUS_ALL ? NON_CAPTURES_PRO_MINUS : GenType; // さもなくば元のまま。 return generateMoves(pos, mlist, recapSq); } @@ -979,8 +979,11 @@ ExtMove* generateMoves(const Position& pos, ExtMove* mlist) template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); -template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); -template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); +template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); +template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); + +template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); +template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); template ExtMove* generateMoves(const Position& pos, ExtMove* mlist); diff --git a/source/movepick.cpp b/source/movepick.cpp index 8ae4dddf2..8727b964a 100644 --- a/source/movepick.cpp +++ b/source/movepick.cpp @@ -363,9 +363,7 @@ Move MovePicker::next_move(bool skipQuiets) { case QCAPTURE_INIT: cur = endBadCaptures = moves; - //endMoves = Search::Limits.generate_all_legal_moves ? generateMoves(pos, cur) : generateMoves(pos, cur); - // → Probcutとかでしか使わないから、CAPTURES_PRO_PLUS_ALLは廃止する。 - endMoves = generateMoves(pos, cur); + endMoves = Search::Limits.generate_all_legal_moves ? generateMoves(pos, cur) : generateMoves(pos, cur); // 駒を捕獲する指し手に対してオーダリングのためのスコアをつける score(); @@ -441,8 +439,7 @@ Move MovePicker::next_move(bool skipQuiets) { cur = (ExtMove*)Math::align((size_t)cur, 32); #endif - //endMoves = Search::Limits.generate_all_legal_moves ? generateMoves(pos, cur) : generateMoves(pos, cur); - endMoves = generateMoves(pos, cur); + endMoves = Search::Limits.generate_all_legal_moves ? generateMoves(pos, cur) : generateMoves(pos, cur); // 駒を捕獲しない指し手に対してオーダリングのためのスコアをつける score(); diff --git a/source/position.cpp b/source/position.cpp index 08479d681..c7ce27b8d 100644 --- a/source/position.cpp +++ b/source/position.cpp @@ -2541,39 +2541,6 @@ void Position::UnitTest(Test::UnitTester& tester) } } - { - // 深いdepthのperftのテストが通っていれば、利きの計算、指し手生成はおおよそ間違っていないと言える。 - - auto section2 = tester.section("Perft"); - - { - auto section3 = tester.section("hirate"); - hirate_init(); - const s64 p_nodes[] = { 0 , 30 , 900, 25470, 719731, 19861490, 547581517 }; - - for (Depth d = 1; d <= 6; ++d) - { - u64 nodes = perft(pos, d); - u64 pn = p_nodes[d]; - tester.test("depth " + to_string(d) + " = " + to_string(pn), nodes == pn); - } - } - - { - auto section3 = tester.section("matsuri"); - matsuri_init(); - - const s64 p_nodes[] = { 0 , 207 , 28684, 4809015, 516925165}; - - for (Depth d = 1; d <= 4; ++d) - { - u64 nodes = perft(pos, d); - u64 pn = p_nodes[d]; - tester.test("depth " + to_string(d) + " = " + to_string(nodes), nodes == pn); - } - } - } - { // 指し手生成のテスト auto section2 = tester.section("GenMove"); @@ -2581,7 +2548,7 @@ void Position::UnitTest(Test::UnitTester& tester) { // 23歩不成ができ、かつ、23歩不成では駒の捕獲にはならない局面。 pos_init("lnsgk1snl/1r4g2/p1ppppb1p/6pP1/7R1/2P6/P2PPPP1P/1SG6/LN2KGSNL b BP2p 21"); - Move move1 = make_move(SQ_24, SQ_23,B_PAWN); + Move move1 = make_move (SQ_24, SQ_23,B_PAWN); Move move2 = make_move_promote(SQ_24, SQ_23,B_PAWN); ExtMove move_buf[MAX_MOVES] , *move_last; @@ -2619,18 +2586,92 @@ void Position::UnitTest(Test::UnitTester& tester) all &= !find_move(move1); all &= find_move(move2); + move_last = generateMoves(pos, move_buf); + all &= find_move(move1); // 歩の不成はこちらに含めることになった。(movegenの実装の修正が難しいので) + all &= find_move(move2); + move_last = generateMoves(pos, move_buf); all &= !find_move(move1); all &= !find_move(move2); + move_last = generateMoves(pos, move_buf); + all &= !find_move(move1); // 歩の不成はこちらには含まれていないので注意。 + all &= !find_move(move2); + tester.test("pawn's unpromoted move", all); + + // 23角不成で5手詰め + // https://github.com/yaneurao/YaneuraOu/issues/257 + pos_init("5B1n1/8k/6Rpp/9/9/9/1+p7/9/K8 b rb4g4s3n4l15p 1"); + // 23角不成(41)と23角成(41) + move1 = make_move (SQ_41, SQ_23, B_BISHOP); + move2 = make_move_promote(SQ_41, SQ_23, B_BISHOP); + all = true; + + move_last = generateMoves(pos, move_buf); + all &= find_move(move1); + all &= find_move(move2); + + move_last = generateMoves(pos, move_buf); + all &= !find_move(move1); + all &= find_move(move2); + + move_last = generateMoves(pos, move_buf); + all &= !find_move(move1); + all &= !find_move(move2); + + move_last = generateMoves(pos, move_buf); + all &= !find_move(move1); + all &= find_move(move2); + + move_last = generateMoves(pos, move_buf); + all &= !find_move(move1); + all &= !find_move(move2); + + move_last = generateMoves(pos, move_buf); + all &= find_move(move1); + all &= find_move(move2); + + tester.test("bishop's unpromoted move",all); + } + } + + { + // 深いdepthのperftのテストが通っていれば、利きの計算、指し手生成はおおよそ間違っていないと言える。 + + auto section2 = tester.section("Perft"); + + { + auto section3 = tester.section("hirate"); + hirate_init(); + const s64 p_nodes[] = { 0 , 30 , 900, 25470, 719731, 19861490, 547581517 }; + + for (Depth d = 1; d <= 6; ++d) + { + u64 nodes = perft(pos, d); + u64 pn = p_nodes[d]; + tester.test("depth " + to_string(d) + " = " + to_string(pn), nodes == pn); + } + } + + { + auto section3 = tester.section("matsuri"); + matsuri_init(); + + const s64 p_nodes[] = { 0 , 207 , 28684, 4809015, 516925165}; + + for (Depth d = 1; d <= 4; ++d) + { + u64 nodes = perft(pos, d); + u64 pn = p_nodes[d]; + tester.test("depth " + to_string(d) + " = " + to_string(nodes), nodes == pn); + } } } { // それ以外のテスト auto section = tester.section("misc"); - { // 盤面の反転 diff --git a/source/types.h b/source/types.h index 2b3523db1..a3bfbadef 100644 --- a/source/types.h +++ b/source/types.h @@ -909,13 +909,21 @@ enum MOVE_GEN_TYPE CAPTURES_PRO_PLUS, // CAPTURES + 価値のかなりあると思われる成り(歩だけ) NON_CAPTURES_PRO_MINUS, // NON_CAPTURES - 価値のかなりあると思われる成り(歩だけ) + CAPTURES_PRO_PLUS_ALL, // CAPTURES_PRO_PLUS + 歩の不成、大駒の不成で駒を取る手も含む + NON_CAPTURES_PRO_MINUS_ALL, // NON_CAPTURES_PRO_MINUS + 大駒の不成で駒を取らない手も含む + // note : 歩の不成で駒を取らない指し手は後者に含まれるべきだが、指し手生成の実装が難しくなるので前者に含めることにした。 + // オーダリング(movepicker)でなんとかするだろうからそこまで悪くはならないだろうし、普段は + // GenerateAllLegalMovesがオンにして動かさないから良しとする。 + // BonanzaではCAPTURESに銀以外の成りを含めていたが、Aperyでは歩の成り以外は含めない。 // あまり変な成りまで入れるとオーダリングを阻害する。 // 本ソースコードでは、NON_CAPTURESとCAPTURESは使わず、CAPTURES_PRO_PLUSとNON_CAPTURES_PRO_MINUSを使う。 // note : NON_CAPTURESとCAPTURESとの生成される指し手の集合は被覆していない。 + // note : CAPTURES_PRO_PLUSとNON_CAPTURES_PRO_MINUSとの生成される指し手の集合も被覆していない。 + // note : CAPTURES_PRO_PLUS_ALLとNON_CAPTURES_PRO_MINUS_ALLとの生成される指し手の集合も被覆していない。 // → 被覆させないことで、二段階に指し手生成を分解することが出来る。 - + EVASIONS, // 王手の回避(指し手生成元で王手されている局面であることがわかっているときはこちらを呼び出す) EVASIONS_ALL, // EVASIONS + 歩の不成なども含む。