There are two main ways of creating weaker levels of chess engine: (1) slowing it down and (2) adding a random factor to evaluation function. My standard way of doing the latter is as follows:
((position->hashKey ^ randomValueObtainedAtGameStart) % noiseValue) - noiseValue / 2;
This pseudo-random value is associated with position hash key, which ensures that it stays the same whenever a position is evaluated, so it does not mess up the search. Xoring by a random value obtained at game start is necessary, so that the engine does not repeat the same game over and over again.
Possible objection is that modulo causes a slowdown. But this is not a problem - typically, evaluation score is disturbed at weaker levels, which are already slowed down by (1)