diff --git a/src/position.cpp b/src/position.cpp index 7d34fe09..43c32acc 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -968,16 +968,6 @@ Value Position::detect_chases(int d, int ply) { // perpetual check repetition or perpetual chase repetition that allows a player to claim a game result. bool Position::rule_judge(Value& result, int ply) const { - // Draw by insufficient material - if (count() == 0 - && (!major_material() || (count() == 0 && major_material() == CannonValue) - || (count() == 4 && count(WHITE) == 1 - && count(BLACK) == 1))) - { - result = VALUE_DRAW; - return true; - } - // Restore rule 60 by adding back the checks int end = std::min(st->rule60 + std::max(0, st->check10[WHITE] - 10) + std::max(0, st->check10[BLACK] - 10), @@ -1026,6 +1016,43 @@ bool Position::rule_judge(Value& result, int ply) const { } } + // Draw by insufficient material + if ([&] { + if (count() == 0) + { + // No attacking pieces left + if (!major_material()) + return true; + + // Only one cannon left on the board + if (major_material() == CannonValue) + { + // No advisors left on the board + if (count() == 0) + return true; + + // The side not holding the cannon can possess one advisor + // The side holding the cannon should only have cannon + if ((count(WHITE) == 2 && count(WHITE) == 1 + && count(BLACK) == 1) + || (count(BLACK) == 2 && count(BLACK) == 1 + && count(WHITE) == 1)) + return true; + } + + // Two cannons left on the board, one for each side, but no other pieces left on the board + if (count() == 4 && count(WHITE) == 1 + && count(BLACK) == 1) + return true; + } + + return false; + }()) + { + result = VALUE_DRAW; + return true; + } + // 60 move rule if (st->rule60 >= 120) {