“…needs to communicate that someone else got there first.” Yes, this is the heart of the locking problem, and it is easily solved by remembering the IP address of that first person, in a two-phase (or two-step) test. This is a simplification, as the entire decentralized locking algorithm does have some necessary complexities to work correctly over the net.
“You’d need a countdown to accept though, so you can’t hold the lock indefinitely”
Yes, great insight. A self-healing robust lock algorithm contains a timeout, to handle “wedged” states resulting from users being cut off from the server unexpectedly.
However, if we assume that the current behavior of the user workflow for selecting and accepting a challenge must be retained unchanged, then your description of how to fix the current problem will not work.
Locking must start with the first user action, in this case clicking on the first green item shown on the Play diagram. It must continue with clicking on the popup user information, and continue with the popup of the challenge information. If you would kindly re-read my description, you will see how it has to work.
But in the real world we don’t have to make this assumption that the process must look the same. Instead of a diagram of green dots, the process can be changed to be a dynamically changing list of challenges, with columns for username, rank, desired time specifications, desired board size, etc.
If we made such a change, the user experience would be far better, and locking would be different (it would still be needed for freedom from errors).
I hope this reply answers all questions and our discussion is done, because this replying takes time I don’t have. Sorry to sound rude, but I must move on, and I have done my best to explain.