Recently, I've been working on a discord bot game for RelatablesNFT.
The specifics aren't too important, but essentially the game works like this: A game is started by an admin, and a secret number of hp is specified. Then, players can click a button, and depending on the amount of NFTs they hold, they will do "damage". All the damage is added up, and the person who crosses the secret number of hp wins. Like a pinata. Or in the case of our bar themed game, a huge opaque mug of beer that is passed around, with the goal being to finish the drink.
Now, onto the more technical details. Whenever a user clicks the button, the callback for the button interaction event is run.
First, the program reads the database and sees the current hp left for the current game. Finally, and subtracts the current hp by the damage done (writes to the db), then the program checks if the user has won (hp at or under 0). Then, it ends the game.
However if one player clicks, then another clicks milliseconds after, in some cases there just hasn't been enough time for the db changes to take place, and so there can be multiple winners.
The main problem is, the two functions being run at the same time aren't aware of the existence of the other, and can't communicate to insure only one winner. I tried a variety of methods, like adding another check to make sure the game didn't end already. None of it worked, unfortunately.
What did work though, is adding a random delay using
Math.random, at which point a global array variable would be looked at. If the array was empty, then the winner would be announced, and something (doesn't matter what) would be added to the array. So, if there was another winner about to be announced, the process would see the array was not empty, and cancel.
Technically, if the random delay was the same or only a few milliseconds different, the global variable could be looked at the same time, and two winners would be announced.
... let's not worry about that