private double HeuristicEval(BoardStates player, OthelloGame game)
        {
            //Based of features of the board that humans have identified.
            //Hints of evaluation from any source I could find
            //idealy these could me optimized using a genetic algorithm,
            //but that is a different project


            const int searchableDepthOverride = 2; //override min-max in favor of complete evaluation
            const int endGame = 20;                //<20 moves is endgame
            const int midGame = 40;                // 20 moves in is midgame


            double value = 0;
            int    empty = game.GetPieceCount(BoardStates.empty);


            if (game.GameComplete)
            {
                return(CompleteEval(player, game));
            }
            else if (empty < searchableDepthOverride)
            {
                return(MinimaxAlphaBeta(game, searchableDepthOverride, int.MinValue, int.MaxValue, player));
            }

            value += coinDiffWeight * Math.Pow((game.GetPieceCount(player) - game.GetPieceCount(~player) + empty - coinDiffOffset), coinDiffPower);
            value += cornerDiffWeight * Math.Pow((game.GetCornerCount(player) - game.GetCornerCount(~player) + empty - cornerDiffOffset), cornerDiffPower);
            value += nearCornerDiffWeight * Math.Pow((game.GetAdjCornerCount(player) - game.GetAdjCornerCount(~player) + empty - nearCornerDiffOffset), nearCornerDiffPower);
            value += avalibleMoveDiffWeight * Math.Pow((game.GetPossiblePlayList(player).Count() - game.GetPossiblePlayList(~player).Count() + empty - avalibleMoveDiffOffset), avalibleMoveDiffPower);
            value += nonTurnableCoinDiffWeight * Math.Pow((game.GetSafePeiceCountEstimation(player) - game.GetSafePeiceCountEstimation(~player) + empty - nonTurnableCoinDiffOffset), nonTurnableCoinDiffPower);
            value += ControlledCornerDiffWeight * Math.Pow((game.GetControlledCorners(player) - game.GetControlledCorners(~player) + empty - ControlledCornerDiffOffset), ControlledCornerDiffPower);
            return(value);
        }