Difficulty adjustment rate
The GetNextWorkRequired function defined in src/pow.cpp is responsible for redefining difficulty by defining the next hash target to keep block production on the desired interval time:
Let's break this function down and jump directly to the important part, recalculating the new difficulty after the difficulty adjustment time interval:
int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
This calculates the time between the current time and the time 2,016 blocks ago(576 for Readercoin):
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
bnPowLimit is the absolute maximum target corresponding to the lowest difficulty.
bnNew is the new target represented in compact form (current target) using the following:
bnNew.SetCompact(pindexPrev->nBits);
When we retarget, we move the target value up or down by the ratio (nActualTimespan/params.nPowTargetTimespan).
bnNew *= nActualTimespan;
bnNew /= params.nPowTargetTimespan;
We cap the difficulty at the powlimit value to avoid using a target above the minimal target hash:
if (bnNew > bnPowLimit) bnNew = bnPowLimit;
Then, the function returns the result as a 32-bit compact representation of the difficulty, like the nbits we used in chainparams.cpp previously: return bnNew.GetCompact();
Thus, if, for some reason, 576 blocks is taking more or less than 24 hours by 20%, each node will lower or increase the difficulty (hash target value) by 20% to bring block production back to the 2.5-minute block target for a few iterations.