private double calUtility () {
        double uti = 0;
        // The more moves made, the more punish on utility.
        uti += gameS.getNumOfMoves() * UTI_PUNISH_MOVES;

        // The more golds gotten, the more bonus on utility.
        uti += gameS.getGoldCollected() * UTI_BONUS_GOTTEN_GOLD;

        uti += getKeyRockNum() * UTI_PUNISH_ROCK_ABOVE;

        uti += getStayPunish();

        if (gameS.getGameState() == GameSimulation.STATE_RUNNING) {
            final int distance = getShortestDistanceToGold();
            assert distance != 0;
            if (distance < ClosestGoldFindingProblem.COST_ROCK) {
                // The shorter distance to gold, the more bonus on utility.
                uti += ((double) UTI_BONUS_POTENTIAL_GOLD / distance);
            }
        } else if (gameS.getGameState() == GameSimulation.STATE_ABORTED) {
            final int distance = getShortestDistanceToGold();
            assert distance != 0;
            if (distance < ClosestGoldFindingProblem.COST_ROCK) {
                // Don't abort if there still is gold can achieve.
                uti += UTI_PUNISH_ABORT;
            } else {
                uti += UTI_BONUS_ABORT;
            }
        } else if (gameS.getGameState() == GameSimulation.STATE_WINNING) {
            uti += UTI_BONUS_WIN;
        } else { // if (gameS.getGameState() == GameSimulation.STATE_FAILED) {
            uti += UTI_PUNISH_LOSE;
        }

        if (willDie) {
            uti += UTI_PUNISH_LOSE;
        }

        return uti;
    }