Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Buncha search related changes.

- Made history updating more optimized.
- Made q-search futility pruning more agressive, but limited to non-PV.
- Limited number of checking moves generated in q-search.
- Changed razoring to be after null move (and made less aggressive).
- Made use of evaluation lazy.
- Increased futility pruning depth.
- LMR now on losing captures as well.
- LMR in PV nodes as well.
  • Loading branch information...
commit c97201a8d7eacfc7f99239eb5e6c821a9aed0911 1 parent bff63b4
unknown authored

Showing 1 changed file with 100 additions and 72 deletions. Show diff stats Hide diff stats

  1. +100 72 GarboChess3/search.cpp
172 GarboChess3/search.cpp
@@ -410,7 +410,6 @@ class MoveSorter
410 410 {
411 411 int historyScore = History[position.Board[GetFrom(moves[i])]][GetTo(moves[i])];
412 412 if (historyScore > 32767) historyScore = 32767;
413   - if (historyScore < -32767) historyScore = -32767;
414 413 moveScores[i] = historyScore;
415 414 }
416 415
@@ -513,7 +512,8 @@ int QSearch(Position &position, SearchInfo &searchInfo, int alpha, const int bet
513 512 }
514 513 }
515 514
516   - const int optimisticValue = eval + 100;
  515 + const int optimisticValue = eval + 50;
  516 + const bool isCutNode = alpha + 1 == beta;
517 517
518 518 MoveSorter<64> moves(position);
519 519 moves.GenerateCaptures();
@@ -543,8 +543,7 @@ int QSearch(Position &position, SearchInfo &searchInfo, int alpha, const int bet
543 543 }
544 544 else
545 545 {
546   - if (pruneValue <= alpha &&
547   - alpha == beta - 1)
  546 + if (pruneValue <= alpha && isCutNode)
548 547 {
549 548 value = pruneValue;
550 549 }
@@ -575,7 +574,7 @@ int QSearch(Position &position, SearchInfo &searchInfo, int alpha, const int bet
575 574 }
576 575 }
577 576
578   - if (depth < -6)
  577 + if (depth < -2)
579 578 {
580 579 // Don't bother searching checking moves
581 580 return eval;
@@ -758,38 +757,16 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
758 757 hashMove = 0;
759 758 }
760 759
761   - int evaluation;
  760 + int evaluation = MaxEval;
  761 + EvalInfo evalInfo;
762 762
763 763 if (!inCheck)
764 764 {
765   - EvalInfo evalInfo;
766   - evaluation = Evaluate(position, evalInfo);
767   -
768   - int razorEval = evaluation + 125;
769   - if (razorEval < beta)
770   - {
771   - // Try some razoring
772   - if (ply <= OnePly)
773   - {
774   - int value = QSearch(position, searchInfo, beta - 1, beta, ply - OnePly);
775   - return max(value, razorEval);
776   - }
777   - razorEval += 175;
778   - if (razorEval < beta && ply <= OnePly * 3)
779   - {
780   - int value = QSearch(position, searchInfo, beta - 1, beta, ply - OnePly);
781   - if (value < beta)
782   - {
783   - return max(value, razorEval);
784   - }
785   - }
786   - }
787   -
788 765 if (ply >= 2 * OnePly &&
789   - evaluation >= beta &&
790 766 !(flags & 1) &&
791 767 // Make sure we don't null move if we don't have any heavy pieces left
792   - evalInfo.GamePhase[position.ToMove] > 0)
  768 + evalInfo.GamePhase[position.ToMove] > 0 &&
  769 + (evaluation = Evaluate(position, evalInfo)) >= beta)
793 770 {
794 771 // Attempt to null-move
795 772 MoveUndo moveUndo;
@@ -824,6 +801,26 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
824 801 return score;
825 802 }
826 803 }
  804 + else
  805 + {
  806 + // Try razoring
  807 + if (ply <= OnePly * 3)
  808 + {
  809 + if (evaluation == MaxEval)
  810 + {
  811 + evaluation = Evaluate(position, evalInfo);
  812 + }
  813 +
  814 + if (evaluation < beta - 300)
  815 + {
  816 + int value = QSearch(position, searchInfo, beta - 1, beta, max(0, ply - (OnePly * 2)));
  817 + if (value < beta)
  818 + {
  819 + return value;
  820 + }
  821 + }
  822 + }
  823 + }
827 824 }
828 825
829 826 MoveSorter<256> moves(position);
@@ -845,11 +842,20 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
845 842 }
846 843 }
847 844
  845 + const int futilityPruningDepth = OnePly * 3;
  846 +
848 847 int moveCount = 0;
849 848 int bestScore = MoveSentinelScore;
850 849 Move move;
851 850 while ((move = moves.NextNormalMove()) != 0)
852 851 {
  852 + if (ply <= futilityPruningDepth &&
  853 + evaluation == MaxEval &&
  854 + moves.GetMoveGenerationState() == MoveGenerationState_QuietMoves)
  855 + {
  856 + evaluation = Evaluate(position, evalInfo);
  857 + }
  858 +
853 859 MoveUndo moveUndo;
854 860 position.MakeMove(move, moveUndo);
855 861
@@ -870,16 +876,11 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
870 876 if (!inCheck &&
871 877 moves.GetMoveGenerationState() == MoveGenerationState_QuietMoves &&
872 878 GetPieceType(position.Board[GetTo(move)]) != PAWN &&
873   - ply <= 2 * OnePly)
  879 + ply <= futilityPruningDepth)
874 880 {
875   - if (ply <= OnePly * 2)
876   - {
877   - value = evaluation + 100;
878   - }
879   - else
880   - {
881   - value = evaluation + 250;
882   - }
  881 + ASSERT(evaluation != MaxEval);
  882 +
  883 + value = evaluation + ((ply / OnePly) * 100);
883 884
884 885 if (value < beta)
885 886 {
@@ -896,19 +897,11 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
896 897
897 898 // Apply late move reductions if the conditions are met.
898 899 if (!inCheck &&
899   - moves.GetMoveGenerationState() == MoveGenerationState_QuietMoves &&
900   - moveCount >= 4 &&
901   - ply >= 3 * OnePly)
  900 + moveCount >= 3 &&
  901 + ply >= 3 * OnePly &&
  902 + moves.GetMoveGenerationState() >= MoveGenerationState_Killer1)
902 903 {
903   - if (moveCount >= 25 &&
904   - GetPieceType(position.Board[GetTo(move)]) != PAWN)
905   - {
906   - newPly = ply - ((5 * OnePly) / 2);
907   - }
908   - else
909   - {
910   - newPly = ply - (2 * OnePly);
911   - }
  904 + newPly = ply - (2 * OnePly);
912 905 }
913 906 else
914 907 {
@@ -926,7 +919,7 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
926 919 value = -Search(position, searchInfo, 1 - beta, newPly, depthFromRoot + 1, 0, isChecking);
927 920 }
928 921
929   - if (newPly <= ply - (2 * OnePly) && value >= beta)
  922 + if (newPly < ply - OnePly && value >= beta)
930 923 {
931 924 // Re-search if the reduced move actually has the potential to be a good move.
932 925 ASSERT(!isChecking);
@@ -966,15 +959,9 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
966 959 const int normalizedPly = ply / OnePly;
967 960 const Square from = GetFrom(move);
968 961 History[position.Board[from]][to] += normalizedPly * normalizedPly;
969   - if (History[position.Board[from]][to] > 200000)
  962 + if (History[position.Board[from]][to] >= 32767)
970 963 {
971   - for (int i = 0; i < 16; i++)
972   - {
973   - for (int j = 0; j < 64; j++)
974   - {
975   - History[i][j] /= 8;
976   - }
977   - }
  964 + History[position.Board[from]][to] /= 2;
978 965 }
979 966 }
980 967
@@ -1011,9 +998,7 @@ int Search(Position &position, SearchInfo &searchInfo, const int beta, const int
1011 998 int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int beta, const int ply, const int depthFromRoot, const bool inCheck)
1012 999 {
1013 1000 ASSERT(inCheck ? position.IsInCheck() : !position.IsInCheck());
1014   -
1015   - // TODO: should probably count PV nodes differently
1016   - searchInfo.NodeCount++;
  1001 + ASSERT(alpha < beta);
1017 1002
1018 1003 if (ply <= 0)
1019 1004 {
@@ -1021,6 +1006,8 @@ int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int be
1021 1006 return QSearch(position, searchInfo, alpha, beta, 0);
1022 1007 }
1023 1008
  1009 + searchInfo.NodeCount++;
  1010 +
1024 1011 if (position.IsDraw())
1025 1012 {
1026 1013 return DrawScore;
@@ -1075,6 +1062,7 @@ int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int be
1075 1062
1076 1063 const int originalAlpha = alpha;
1077 1064 int bestScore = MoveSentinelScore;
  1065 + int moveCount = 0;
1078 1066
1079 1067 Move move;
1080 1068 while ((move = moves.NextNormalMove()) != 0)
@@ -1088,7 +1076,26 @@ int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int be
1088 1076
1089 1077 // Search move
1090 1078 const bool isChecking = position.IsInCheck();
1091   - const int newPly = (isChecking || singular) ? ply : ply - OnePly;
  1079 + int newPly;
  1080 +
  1081 + if (isChecking || singular)
  1082 + {
  1083 + newPly = ply;
  1084 + }
  1085 + else
  1086 + {
  1087 + if (!inCheck &&
  1088 + moveCount >= 7 &&
  1089 + ply >= 3 * OnePly &&
  1090 + moves.GetMoveGenerationState() == MoveGenerationState_QuietMoves)
  1091 + {
  1092 + newPly = ply - (OnePly * 2);
  1093 + }
  1094 + else
  1095 + {
  1096 + newPly = ply - OnePly;
  1097 + }
  1098 + }
1092 1099
1093 1100 if (bestScore == MoveSentinelScore)
1094 1101 {
@@ -1111,7 +1118,20 @@ int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int be
1111 1118 }
1112 1119 }
1113 1120
  1121 + if (newPly < ply - OnePly && value >= beta)
  1122 + {
  1123 + // Re-search if the reduced move actually has the potential to be a good move.
  1124 + ASSERT(!isChecking);
  1125 + ASSERT(!inCheck);
  1126 +
  1127 + newPly = ply - OnePly;
  1128 + ASSERT(newPly > 0);
  1129 +
  1130 + value = -SearchPV(position, searchInfo, -beta, -alpha, newPly, depthFromRoot + 1, isChecking);
  1131 + }
  1132 +
1114 1133 position.UnmakeMove(move, moveUndo);
  1134 + moveCount++;
1115 1135
1116 1136 if (value > bestScore)
1117 1137 {
@@ -1124,16 +1144,24 @@ int SearchPV(Position &position, SearchInfo &searchInfo, int alpha, const int be
1124 1144
1125 1145 if (value >= beta)
1126 1146 {
1127   - // TODO: update history
1128 1147 StoreHash(position.Hash, value, move, ply, HashFlagsBeta);
1129 1148
1130 1149 // Update killers (only for non-captures/promotions)
1131   - if (position.Board[GetTo(move)] == PIECE_NONE &&
1132   - GetMoveType(move) != MoveTypePromotion &&
1133   - move != searchInfo.Killers[depthFromRoot][0])
  1150 + const Square to = GetTo(move);
  1151 + if (position.Board[to] == PIECE_NONE)
1134 1152 {
1135   - searchInfo.Killers[depthFromRoot][1] = searchInfo.Killers[depthFromRoot][0];
1136   - searchInfo.Killers[depthFromRoot][0] = move;
  1153 + if (GetMoveType(move) != MoveTypePromotion &&
  1154 + move != searchInfo.Killers[depthFromRoot][0])
  1155 + {
  1156 + searchInfo.Killers[depthFromRoot][1] = searchInfo.Killers[depthFromRoot][0];
  1157 + searchInfo.Killers[depthFromRoot][0] = move;
  1158 + }
  1159 +
  1160 + const Square from = GetFrom(move);
  1161 + if (History[position.Board[from]][to] >= 32767)
  1162 + {
  1163 + History[position.Board[from]][to] /= 2;
  1164 + }
1137 1165 }
1138 1166
1139 1167 return value;
@@ -1309,7 +1337,7 @@ Move IterativeDeepening(Position &rootPosition, const int maxDepth, int &score,
1309 1337 int bestScore;
1310 1338
1311 1339 // Iterative deepening loop
1312   - for (int depth = 1; depth <= min(maxDepth, 99); depth++)
  1340 + for (int depth = 1; depth <= min(maxDepth, 65); depth++)
1313 1341 {
1314 1342 for (int i = 0; i < moveCount; i++)
1315 1343 {

0 comments on commit c97201a

Please sign in to comment.
Something went wrong with that request. Please try again.