On (2): this is correct. In fact you don't even have tio finish move generation: as soon as you generate a move that captures the King, you can abort the generation and return +INFINITY.
(1) is related with your last remark. Indeed what I wrote was unclear. When the user inputs an illegal move, putting it in userMove and calling Searc() will make the latter return something different from OK_CODE, without performing a move, and you could print an illegal-move error message for the user.
The case I was discussing was when you want the computer to make a move, however. You want it to make the best move according to its search. So the program must put something invalid in userMove before it calls Search(), to make sure the test move == userMove in the root will always fail. Because if the test would succeed, Search() would immediately return, having played that move, even if it was not the best. And it might not have searched all moves, and thus might not even have seen the best.
So you would do smoething like
Code: Select all
userMove = INVALID;
Search(ply=1, depth=maxDepth, ...); // this would set the variable bestMove
userMove = bestMove; // now do what you would do if the user had typed that move
Search(ply=1, depth=2, ...);
The rest of what I was saying in the paragraph you quoted was this:
Around the for(ALL_MOVES) loop, you usually have another loop that iterates over increasing search depth. (Definitely in the root, but my engines do it in any node.) Such iteration would increase the actually used depth' iterDepth' until you reach the depth specified in the call of Search(). But in the root you in general would want to stop based on time, not on a maximum depth. So you would request a liberal depth in the call to Search, like 99, which would not be reached anyway, so that it always will continue as long as time allows.
In micro-Max I then do something like this:
Code: Select all
Search(ply, depth, ...)
{
iterDepth = START_DEPTH; // in the root, this would aleways be 1
while(iterDepth <= depth) {
...
for(ALL_MOVES) {
...
if(score > bestScore) { bestScore = score; bestMove = move; }
}
...
iterDepth = NEXT_DEPTH(iterDepth); // in the root, this would add 1
if(ply == 1 && TIME_IS_UP) { // in the root only
iterDepth = 2; depth = 2; // fool the loop to do exactly one more iteration
userMove = bestMove; // and to think the user typed this move
}
}
}