@@ -1033,24 +1033,34 @@ Value Endgame<RK, EG_EVAL_ANTI>::operator()(const Position& pos) const {
10331033}
10341034
10351035
1036- // / K vs N. The king usally wins, but there are a few exceptions.
1036+ // / K vs N. The king usually wins, but there are a few exceptions.
10371037template <>
10381038Value Endgame<KN , EG_EVAL_ANTI >::operator ()(const Position& pos) const {
10391039
10401040 assert (pos.endgame_eval () == EG_EVAL_ANTI );
10411041
10421042 Square KSq = pos.square <COMMONER >(strongSide);
10431043 Square NSq = pos.square <KNIGHT >(weakSide);
1044+ Bitboard kingAttacks = attacks_bb<KING >(KSq) & pos.board_bb ();
1045+ Bitboard knightAttacks = attacks_bb<KNIGHT >(NSq) & pos.board_bb ();
1046+ bool strongSideToMove = pos.side_to_move () == strongSide;
1047+
1048+ // Loss in 1 play
1049+ if (strongSideToMove ? kingAttacks & NSq : knightAttacks & KSq)
1050+ return VALUE_TB_LOSS_IN_MAX_PLY + 1 ;
1051+ // Win in 2 ply
1052+ if (kingAttacks & knightAttacks)
1053+ return VALUE_TB_WIN_IN_MAX_PLY - 2 ;
1054+ // Loss in 3 ply
1055+ if (strongSideToMove ? knightAttacks & KSq : kingAttacks & NSq)
1056+ return VALUE_TB_LOSS_IN_MAX_PLY + 3 ;
1057+
1058+ Value result = Value (push_to_edge (NSq, pos)) - push_to_edge (KSq, pos);
1059+ // The king usually wins, but scenarios with king on the edge are more complicated
1060+ if (!(KSq & (FileABB | FileHBB | Rank1BB | Rank8BB)))
1061+ result += VALUE_KNOWN_WIN ;
10441062
1045- // wins for knight
1046- if (pos.side_to_move () == strongSide && (attacks_bb<KNIGHT >(NSq) & KSq))
1047- return -VALUE_KNOWN_WIN ;
1048- if (pos.side_to_move () == weakSide && (attacks_bb<KNIGHT >(NSq) & attacks_bb<KING >(KSq)))
1049- return VALUE_KNOWN_WIN ;
1050-
1051- Value result = VALUE_KNOWN_WIN + push_to_edge (NSq, pos) - push_to_edge (KSq, pos);
1052-
1053- return strongSide == pos.side_to_move () ? result : -result;
1063+ return strongSideToMove ? result : -result;
10541064}
10551065
10561066// / N vs N. The side to move always wins/loses if the knights are on
0 commit comments