Purpose: A refinement of alpha-beta that uses null-window searches to prove most moves are inferior cheaply, re-searching only when one turns out to be better. Typically 10-20% faster than plain alpha-beta on well-ordered trees. Also called Principal Variation Search (PVS).

The Idea

Alpha-beta already prunes; Negascout adds a bet:

If the moves are well ordered, the first move is almost always the best. So search the first move with the full window , and search every other move with the null window , which is much cheaper. A null-window search cannot return an exact value — only "" or "". If it says (the usual case), the move is refuted and we are done. If it says , the bet failed and we re-search that move with the full window.

Code

int negascout(Node& n, int depth, int alpha, int beta) {
    if (depth == 0 || n.terminal()) return evaluate(n);
 
    bool first = true;
    for (Move m : orderedMoves(n)) {
        n.apply(m);
        int score;
        if (first) {
            score = -negascout(n, depth - 1, -beta, -alpha);
            first = false;
        } else {
            score = -negascout(n, depth - 1, -alpha - 1, -alpha);   // null window
            if (alpha < score && score < beta)                      // bet failed
                score = -negascout(n, depth - 1, -beta, -score);    // re-search
        }
        n.undo(m);
 
        alpha = max(alpha, score);
        if (alpha >= beta) break;                                   // cutoff
    }
    return alpha;
}

Complexity

  • Same worst case as alpha-beta:
  • Best case (perfect move ordering): — the alpha-beta optimum
  • In practice: 10-20% fewer nodes than alpha-beta given good ordering; worse than alpha-beta given bad ordering, because of re-searches

Move ordering is everything

Negascout only pays off when the first move really is usually best. Without good ordering, the re-searches cost more than they save. The standard ordering tools are:

  • transposition table move from a previous, shallower search;
  • iterative deepening — search depth 1, 2, 3, …, using each result to order the next;
  • killer moves — moves that caused a cutoff at the same ply elsewhere;
  • history heuristic — a global score per move based on past cutoffs;
  • MVV-LVA for captures in chess.

The family of alpha-beta refinements

TechniqueIdea
Negamaxone code path instead of separate min/max
Negascout / PVSnull-window all but the first move
MTD(f)all searches are null-window, driven by a bisection on the root value
Aspiration windowsstart with a narrow window around the previous iteration’s score
Quiescence searchextend past the horizon on captures to avoid the horizon effect
Null move pruninggive the opponent a free move; if still winning, prune
Late move reductionssearch later (presumed worse) moves at reduced depth

MTD(f) takes the null-window idea to its conclusion and is elegant, but is highly dependent on a good transposition table; PVS is the more robust default and is what most engines use.

Variants / Use Cases