After some reconstructing of the makeMove, umakeMove, makeNull and unmakeNull methods I ran into a long streak of errors popping up in just about all positions.
I sat for a few hours commenting out all complicating code like transposition tables, null moves, futility pruning, quiescent search etc. trying to isolate the error but it kept appearing at the exact same spots. The perft numbers worked perfectly, so I had to look for the error in the search.
So I started printing the moves to see if I could find a pattern. I had found a position where the error appeared after 'only' 3000 nodes so the print out was atleast manageable.
At first I thought it was the legal move check that was the problem because that was the most obvious thing that was made differently from a plain perft search.
However, after 4 hours or so I concluded it had something to do with captures and it seemed to involve the hash move.
By then the time was 2am so I decided to try in the morning. And with a fresh mind I immedatiatly drew the obvious conclusion... hash moves depend on zobrist keys to work correctly of course, and there is a code segment in the makeMove method that updates the zobrist for captures.
And of course there the problem was, I had 'simplified' that part of the code and instead of removing black pieces from the zobrist I removed white and vice versa.
So it was the 'other' thing the search does differently execept for legal moves, it uses a transposition table. :)
This was so much fun I almost considered starting to put in intentional bugs just to enjoy solving them. Or not.