IID in the root is called ID, and you definitely do that there. Null-move pruning happens when the null-move score is above beta, which is impossible when beta = INFINITY, as it would be in the root. So you do not do it, but not specifically because it is in the root, but because beta is too large there. Leaving in the normal code (which likely would not even do a null-move search when curEval < beta) doesn't do any harm, as it would not be triggered.Sven wrote: ↑Sat Feb 20, 2021 6:11 pmThere a lot of search features that should not be used at the root node, e.g. null move pruning or other kinds of pruning, IID, or even endgame tablebase probing. TT probing is just one of them IMO. Also there is at least one thing you only do at the root node: printing a new PV that has just been found by raising alpha. So you need to know anyway whether you are at the root, so it is no additional penalty to also suppress the useless TB probing there.
Printing the PV is indeed root-specific, and I usually put an if(ply == 0) section for that directly after constructing the new PV on an alpha increase that stays below beta. (Which must be done in every node, with the tri-angular method.) Because this code section of Search() is hardly ever executed (only in PV nodes, which is a negligible fraction of the total number of nodes), putting an extra if() that can be predicted with 99.99999% accuracy to be if(false) thus is not harmful at all. In that same conditional I then also correct alpha back to alpha - multiPvMargin.
EGT probing could ba an issue, depending on how you implement that. If you probe directly after MakeMove(), instead of at the top of the child node, it would be OK to do it in the root.
So yes, I have to know whether I am in the root (which I can see from ply==0). But there needs to be only a single place where that matters, after the alpha increase. All root extras can be controlled from there.
It usually gives me more of a head-ache to use the same Search routine also for QS. In particular when you use self-deepening, it is nasty when you don't know whether the d=1 iteration will abort after the captures, (because QS sufficed), or whether you have to a full d=1 (or even d>1) with non-captures as well, where standing pat was not allowed (while in QS you would like stand-pat to raise alpha before you search the captures.