I’ll start this with a disclaimer: I’m not very good at chess.

That’s not too big an issue, thanks to the great number of chess engines that have adaptable difficulty, just set it to easy, and keep putting it up until you have trouble winning.

The problem with this approach is that difficulty is typically graded in pretty large steps - I might be better than ‘Easy’, but worse than ‘Medium’.

To this end, I was inspired by Really Bad Chess, which is a mobile game that learns how good you are and gives you worse pieces the better you get.

Shecs is a PWA, so it is playable on a desktop as well as on mobile, and plays nicely offline. It lets you set the difficulty as a percentage, and randomises your pieces depending on that.

The actual difficulty of the engine itsef is constant, and I made use of the P4WN Chess engine, mainly because it’s so lightweight (), so can be sent to the client for offline use.

It took a few attempts to make a good randomisation algorithm, because I needed an approach that would satisfy two criteria:

  • It must allow weighting by difficulty
  • It must make the game exciting

The latter item is somewhat subjective, but what I mean by an exciting game is one that pits, for example, a standard side against a side with an additional 2 rooks. A boring game, on the other hand, would be one that pits an entire side of pawns against a side of pawns with 3 knights.

My first approach was simply to give each piece a score, then multiply the difficulty by a random number and see which piece has the closest score. This failed, because with a difficulty of 50%, you would never get a random number higher than ½, and so would never get a queen. It produced properly weighted sides, but they were boring.

What I settled on in the end was the technique of picking three random pieces from a bag (containing infinite pieces), and if the random number was smaller than the difficulty, the player’s side would get the best piece, while the opposing side would get the worst piece. With this technique, we get a fairly random (but weighted towards the extreme end of the scale) selection of pieces, satisfying my second criteria, as well as distributing these pieces based on difficulty, fulfilling my first criteria.