@@ -91,47 +91,77 @@ def quiescence_search(
9191 Returns:
9292 - best_score: returns best move's score.
9393 """
94- if board .is_stalemate ():
95- return 0
94+ in_check = board .is_check ()
9695
9796 if board .is_checkmate ():
9897 return - self .config .checkmate_score
9998
100- stand_pat = self .eval_board (board )
99+ if board .is_stalemate ():
100+ return 0
101101
102- # recursion base case
103- if depth == 0 :
104- return stand_pat
102+ # Draw detection: fifty-move rule, insufficient material
103+ # Note: Repetition is checked after making moves, not here
104+ if board .is_fifty_moves () or board .is_insufficient_material ():
105+ return 0
105106
106- # beta-cutoff
107- if stand_pat >= beta :
108- return beta
107+ stand_pat = self .eval_board (board )
108+
109+ # When in check, we can't use stand-pat for pruning (position is unstable)
110+ # We must search all evasions. However, still respect depth limit.
111+ if in_check :
112+ # In check: search all evasions, but don't use stand-pat for cutoffs
113+ if depth <= 0 :
114+ # At depth limit while in check: return evaluation
115+ # (not ideal but prevents infinite recursion)
116+ return stand_pat
117+
118+ best_score = float ("-inf" )
119+ moves = list (board .legal_moves ) # All evasions
120+ else :
121+ # Not in check: normal quiescence behavior
122+ # recursion base case
123+ if depth <= 0 :
124+ return stand_pat
125+
126+ # beta-cutoff: position is already good enough
127+ if stand_pat >= beta :
128+ return beta
109129
110- # alpha update
111- alpha = max (alpha , stand_pat )
130+ # Use stand-pat as baseline (we can always choose not to capture)
131+ best_score = stand_pat
132+ alpha = max (alpha , stand_pat )
112133
113- # get moves for quiescence search
114- moves = organize_moves_quiescence (board )
134+ # Only tactical moves when not in check
135+ moves = organize_moves_quiescence (board )
115136
116137 for move in moves :
117138 # make move and get score
118139 board .push (move )
119- score = - self .quiescence_search (
120- board = board ,
121- depth = depth - 1 ,
122- alpha = - beta ,
123- beta = - alpha ,
124- )
140+
141+ # Check if this move leads to a repetition (draw)
142+ if board .is_repetition (2 ):
143+ score = 0.0 # Draw score
144+ else :
145+ score = - self .quiescence_search (
146+ board = board ,
147+ depth = depth - 1 ,
148+ alpha = - beta ,
149+ beta = - alpha ,
150+ )
151+
125152 board .pop ()
126153
154+ if score > best_score :
155+ best_score = score
156+
127157 # beta-cutoff
128158 if score >= beta :
129159 return beta
130160
131161 # alpha-update
132162 alpha = max (alpha , score )
133163
134- return alpha
164+ return best_score
135165
136166 def negamax (
137167 self ,
0 commit comments