You should start with some control theory when adjusting difficulty.
I suggest looking at a Kalman filter first. It is provably the optimum when the noise is random. It is just a few multiplications and is easy to implement in a few lines of C.
But at a high level, don't try to write this in a small C function. You have trillions of clock cycles between blocks, fork out some $$$ and write a decent high level implementation.
Why not add something like liboctave or R to the source code? Then you could use ready-made implementations of these things.
In order to create a kalman filter, you need to create a model of how the dynamics of the system should behave. If the goal of the control system is to keep the block output at a fixed rate, then the distance from that rate is the error you want to correct.
In addition to this error, you have a noise generator which represents your inability to control correctly. The kalman filter will over time adjust and learn the standard deviation for the noise and thus apply the optimum error correction (adjustment to difficulty).
What you generally need to estimate is the correlation matrix between the variables in your model.
You want your underlying model to be as simple as possible, but also as correct as possible. Some variables in a model could for example be: the % increase in issued coins by a block, the difficulty, the difficulty error (difference from ideal inter-block time), the estimated hashing power of the network (which requires a separate model to estimate), the relative exchange value wrt bitcoin, etc.
You also need to estimate the correlation matrix between these variables, but this is mostly to make the filter more efficient. You can set the correlations to 0 if you want.
A last point I want to make is that hard forks are not bad. It has been shown again and again that bitcoin does not solve distributed consensus. Both because the amount of computing power is unknown, and more politically because hashing power is already too concentrated. Changing the algorithm on a deployed coin is something the users/developers of the coins control, not the miners, unlike what people tend to believe. It doesn't matter how much hashing power an attacker has if he refuses to run the same algorithm as the users of a coin requires.