@Override
	public MOVE getMove(Game game, long timeDue) {
		int currentNode = game.getPacmanCurrentNodeIndex();

		// get possible moves and sane moves
		MOVE[] possibleMoves = game.getPossibleMoves(currentNode);
		MOVE[] saneMoves = filterSaneMoves(possibleMoves, game, currentNode);
		if (saneMoves.length == 0)
			saneMoves = possibleMoves;
		
		// compute move "possibilities"
		EnumMap<MOVE, Double> moveChances = new EnumMap<MOVE, Double>(MOVE.class);
		for (MOVE move : saneMoves) {
			Vector features = extendFeatures(getFeatures(game, currentNode, move));
			double value = getValueFunctionEstimation(features);
			double expValue = Math.exp(value);
			moveChances.put(move, expValue);
		}
		
		// compute actual possibilities
		double scale = getMovesNormalizationScale(saneMoves, moveChances);
		for (MOVE move : saneMoves) {
			moveChances.put(move, moveChances.get(move) * scale);
		}
		
		// select move
		double random = Math.random();
		double aux = 0;
		for (MOVE move : saneMoves) {
			aux += moveChances.get(move);
			if (aux >= random)
				return move;
		}

		return MOVE.NEUTRAL;
	}