22#include " eval.h"
33#include " timeman.h"
44#include " uci.h"
5+ #include " movepick.h"
56#include < atomic>
67#include < moves_io.h>
78#include < position.h>
@@ -30,7 +31,7 @@ namespace engine
3031 *pv++ = *childPv++;
3132 *pv = Move::none ();
3233 }
33- Value doSearch (Board &board, int depth, Session &session, int ply = 0 )
34+ Value doSearch (Board &board, int depth, Value alpha, Value beta, Session &session, int ply = 0 )
3435 {
3536 std::fill (std::begin (session.pv [ply + 1 ]), std::end (session.pv [ply + 1 ]),
3637 Move::none ());
@@ -49,9 +50,20 @@ namespace engine
4950 Move preferred = Move::none ();
5051 if (TTEntry *entry = search::tt.lookup (hash))
5152 {
53+ preferred = Move (entry->getMove ());
5254 if (entry->getDepth () >= depth)
5355 {
54- preferred = Move (entry->getMove ());
56+ Value ttScore = entry->getScore ();
57+ TTFlag flag = entry->getFlag ();
58+
59+ if (flag == TTFlag::EXACT)
60+ return ttScore;
61+
62+ if (flag == TTFlag::LOWERBOUND && ttScore >= beta)
63+ return ttScore;
64+
65+ if (flag == TTFlag::UPPERBOUND && ttScore <= alpha)
66+ return ttScore;
5567 }
5668 }
5769 if (depth == 0 )
@@ -64,18 +76,16 @@ namespace engine
6476 board.legals (moves);
6577 if (!moves.size ())
6678 {
67- // Checkmate or stalemate handling should go here if you implement it
6879 session.pv [ply][0 ] = Move::none ();
6980 return board.checkers () ? -MATE (ply) : 0 ;
7081 }
71-
82+ movepick::orderMoves (board, moves, preferred, ply);
7283 for (Move move : moves)
7384 {
7485
7586 board.doMove (move);
7687
77- // ---- RECURSIVE CALL ----
78- Value childScore = doSearch (board, depth - 1 , session, ply + 1 );
88+ Value childScore = doSearch (board, depth - 1 , -beta, -alpha, session, ply + 1 );
7989
8090 board.undoMove ();
8191
@@ -91,17 +101,43 @@ namespace engine
91101 update_pv (session.pv [ply], move, session.pv [ply + 1 ]);
92102 }
93103
94- // Local time check (optional but fine)
104+ if (score > alpha){
105+ alpha = score;
106+ if (!board.isCapture (move))
107+ historyHeuristic[from][to] += depth * depth;
108+ }
109+ if (alpha >= beta)
110+ {
111+ if (!board.isCapture (move))
112+ {
113+ if (killerMoves[ply][0 ] != move)
114+ {
115+ killerMoves[ply][1 ] = killerMoves[ply][0 ];
116+ killerMoves[ply][0 ] = move;
117+ }
118+ }
119+
120+ break ;
121+ }
122+
95123 if (session.tm .elapsed () >=
96124 session.tm .optimum () ||
97125 stopSearch.load (std::memory_order_relaxed))
98126 return VALUE_NONE;
99127 }
100128
101- // Store only if valid
102129 if (maxScore != -VALUE_INFINITE)
103- search::tt. store (hash, session. pv [ply][ 0 ], maxScore, depth, TTFlag::EXACT) ;
130+ TTFlag flag ;
104131
132+ if (maxScore <= alphaOrig)
133+ flag = TTFlag::UPPERBOUND;
134+ else if (maxScore >= beta)
135+ flag = TTFlag::LOWERBOUND;
136+ else
137+ flag = TTFlag::EXACT;
138+
139+ search::tt.store (hash, session.pv [ply][0 ], maxScore, depth, flag);
140+ }
105141 return maxScore;
106142 }
107143 void search::search (const chess::Board &board,
@@ -115,9 +151,10 @@ namespace engine
115151 chess::Move lastPV[MAX_PLY]{};
116152 for (int i = 1 ; i < timecontrol.depth ; i++)
117153 {
154+ for (int i=0 ;i<64 ;i++)for (int j=0 ;j<64 ;j++)movepick::historyHeuristic[i][j]/=2 ;
118155 session.nodes = 0 ;
119156 auto board_ = board;
120- Value score_ = doSearch (board_, i, session);
157+ Value score_ = doSearch (board_, i, -VALUE_INFINITE, VALUE_INFINITE, session);
121158 if (session.tm .elapsed () >=
122159 session.tm .optimum () ||
123160 stopSearch.load (std::memory_order_relaxed) || score_ == VALUE_NONE)
0 commit comments