Ligretto is a card game where reaction speed, and keeping a good overview on the state of the playing field matters a lot. However, there is also a large dose of chance in it, since you can get very lucky with the cards you get dealt. In this post, I want to figure out how much the outcome of the game is influenced by skill (speed, reaction time, overview of the game), and how much is luck.
1 The code is not yet available because I am still in the process of changing around a few things.
The rules of Ligretto
Wikipedia summarizes the rules of the game really well - I’ll try to make it even shorter here:
There are cards of four different colors, with values 1-10. Only cards of the same color, and the consecutive value of the current ‘top-card’ of the stack can be laid on top of the stack (cards with value 1 can always be laid down to start a new stack). Every player has a number of open cards on the table, and a number of turned cards stacked next to them. If a table card is laid on a stack on the field, or starts a new stack, the empty spot is filled up with a card from the stack.
In addition, every player has hand cards, which the players go through repeatedly (and only look at every 3rd card) to check if one of these can be laid down. If someone finished all his cards from the stack, the game is over and the points are calculated: the number of cards laid down by the player, minus the remaining cards on the stack, times two. All players play simultaneously, thus competing in laing down cards first, and laying as many as possible as quickly as possible.
The overall game usually ends once one of the players has a cumulative sum of points that is higher than some threshold.
As is tradition, no one actually plays any game how its intended by the manufacturer (Monopoly and the auction of property being the most famous case here). In our case, we usually do the shuffling of the hand cards slightly different: we shuffle every time you went through all your hand cards instead of the intended ‘only when no one can put down any cards anymore’.
I will simulate both cases, and check how this changes the outcome of the games2.
2 I am assuming that playing be the proper rules lessens the advantage of quicker players somewhat.
Simulating the game
Everyone is playing simultaneously, so a multithreaded approach seems to make sense to simulate the game on a first glance. Instead of going down that route (and probably fighting with memory, access and deadlock issues), I decided to simulate an ‘action-based’ approach, meaning that I store the state of the playing field, query all the players if they can do something, and figure out when they would do it.
I.e. I generate the events/actions coming from the players, and apply them one by one to the state depending on when the player would do it. Such an approach also allows to incorporate reaction time, how long a specific player takes to lay down a card, and allows a different player to ‘intercept’ an opponent by having e.g. a faster reaction time.
This is repeated until a player is finished (i.e. if no cards are on one players stack anymore).
The simulation of the game keeps track of the state of the playing field, and the state of all players.
- The state of the playing field consists of the currently active stacks of cards on the playing field, and the minimum time-stamp of all players as the current time.
- The state of each player consists of the hand cards, the index which points to the currently available hand card, the open cards on the table, and the cards on the stack.
Action based system, and time keeping
The state of the game can be altered by actions taken by a player. Each of these actions take some time, and if a player is too slow, another player can beat the previous one to laying down a card onto a stack. Hence, in the simulation, the actions are modeled to be taking 3 time-slices: i) the time until an action is actually taken, ii) the time the action takes, and iii) the time after an action was taken
The possible actions are:
- Proceeding to the next handcard
- Laying down a handcard
- Laying down a card from the table, and subsequently uncovering a card from the stack
- Shuffling the handcards
If a player is intercepted while laying down a card, the pre-action time will still count towards the players current time, which is used to figure out when he can continue with the next action.
Shuffling is a science in itself, mostly perfected at casinos. In our case, we are interested specifically in what happens in between rounds - shuffling there is not perfect, and has an influence on the following round if the shuffling is not really randomizing the cards. It often happens that several consecutive cards of the same color stay together if shuffling in between rounds is not done properly.
We can visualize a few versions of shuffling by drawing colored squares, with the squares being colored consecutively in a lighter shade depending on the value of the card.
A uniform shuffling would look like this:
A repeated overhand shuffle, and a repeated imperfect riffle shuffle would lead to the images below:
It should be fairly clear that an overhand shuffle is definitely not sufficient for the task of actually shuffling the cards. The shortcomings of the overhand shuffle disappear if the process is repeated often enough, but I am assuming that at this point, the player definitely does not shuffle that often.
After a round, the cards are sorted again to be able to count them - they are not completely sorted by ‘deck’, but rather by the person they belong to. Simply removing the cards of the ‘opposing’ player, and stacking the remaining cards on order on top of the hand cards looks like:
shuffling this perfectly would lead to
applying the repeated shuffles from above to the initial ordering from a game would lead to
We see that there is still a considerable amount of ‘order’3 in the deck, even after 4 underhand shuffles, whereas the riffle shuffle leads to ‘randomness’ much faster. Realistically, no one is really doing the overhand shuffle 10 times, and even if - visual inspection still seems to point to it having more ‘order’ than the imperfect riffle shuffle after just one iteration.
3 'Order', respectievely how well something is a bit vague in this context - after all it could be that even a perfect shuffle could lead to all colors being together! What it boils down to is the likelihood of the blocks staying together: In a perfect shuffle that is fairly unlikely. Doing an overhand shuffle however leads to this result much more often!
In the following, I will only look at two players playing the game with two sets of cards each (i.e. 4 colors, values 1-10, times two) if not specifically mentioned otherwise.
Before running experiments, I briefly want to introduce my hypotheses - the things I want to prove or disprove. In addition, I’ll do a few general analyses to decide if the simulation even makes sense, and to gain intuition on the simulation and the parameters I introduced.
The specific hypotheses I have and want to prove4 (which is why I am doing this whole thing) are:
4 Prove is really too strong of a word here - I am actually searching for evidence for/against the hypothesis. Conclusively proving it is out of reach here.
- Badly shuffling the deck after a round gives a significant advantage (due to how the deck is assembled - see above - the cards are fairly in order in the beginning. Having them in order should help you winning.)
- Luck plays a large role - Reformulating this: Given that I lose, what is the probability that I am actually the worse player? 5
5 Sounds like a statistics exercise after you just covered bayes formula? It does because it basically is one!
And the things I have been wondering since quite some time:
- When do we run into deadlocks (i.e. no one can lay down a card anymore)?
- Does having high table cards in the beginning lead to a lower probability of winning? (I assume it should - since you can’t lay them down at the beginning, when your opponent can already do so. But how big of a difference is it?)
Before actually starting to look at the hypotheses above, I’ll run a few small things that I am interested at, starting with:
When are cards laid down?
When during the game are cards actually laid down? Does the speed of the initially laid down cards predict the winner? We look at the cumulative sum of the laid down cards over time, coloring the winning lines green, the other red.
A slow-ish start can be seen, and a slight acceleration in pace for poth players. Towards the end of the game, the speed decreases for both players, which is in part because long games tend to have a slower pace, and in part because a lot of cards are already laid down, and the left over cards are more specific.
We also see that there is a light tendency that the winner also laid down more cards, and had a slightly higher pace than the losing player.
Continuing with the last hypothesis: we compute the sum of the values of the initial table cards of both players, and count the number of wins of player 1. We then compute the probability of a win simply by dividing the number of wins in a given combination of start-sums by the number of games played.
Ignoring the spurious values of either 1 or 0 where only a low number of games was played, we see:
- The expectation of having a fairly equal win-rate along the symmetry-axis is fulfilled
- A high win-rate is found where player 1 has a low initial sum, and player 2 has a high one.
- From this plot, it seems like the ‘isolines’ would be along the ‘y=x+b’-line, meaning that only the difference in the sum matters
It is likely that it matters how a sum is made up when examining this result closer - do three 3s and two 7s lead to the same result as two 10s and three 1s? Or more generally posed: what is the best starting-configuration for a given sum?
We carry on with the shuffling-question: How big is the advantage of a player that shuffles badly, but plays equally well? And posed the other way around: How much worse (slower/miss cards) - if at all - can a player be, and still win an equal amount by shuffling badly?
We first check what the influence of bad shuffling on the win-rate of two otherwise equal players is. We do that by having one player shuffle differently fom the perfect shuffle provided by python.
First, it is clear that not shuffling provides a clear advantage. Secondly it also becoms obvious that we need to shuffle a certain amount of times using the imperfect riffle shuffle. And last but not least, a perfect riffle brings the stack in such ‘unorder’ that the win rate is the same as when shuffling perfectly. This has probably to do with the fact that only every 3rd card is looked at, which might lead to a fair distribution of cards.
Attentiveness and Speed
We continue by looking at the influence of speed and ‘attentiveness’, i.e., how often a player misses a possibility to lay down a card. For both analyses, we plot the distribution of the win-rate for a certain speed/attentiveness for both players, to see something.
Starting with the ‘attentiveness’, we get the following:
Here, we define a win as having more points that the other player. It is visible that, while the better player generally has a higher win-probability, there is a quite wide margin where it is unclear who the better player is from only a small number of games (as indicated by the high variance in the results).
A similar result occurs when plotting the win rate against the speed of a player:
In both cases, I averaged over 20 games to compute an estimate for the win rate and the standard deviation of the winrate. Obviously, having to average over 20 games to get a decent estimate of who is actually better is not optimal. Ideally, there would be less luck involved, and more skill.
Discussion and Further analysis:
Over the course of writing this post I played ligretto quite a few times - and noticed that there are a lot of behaviours that are very hard to reproduce. From strategically not laying down a card, or laying it down just a bit later, so that the other person is occupied, to paying attention to a very specific stack to not miss the opportunity to lay down a card.
These things influence the game, and take all of this analysis/simulation a bit further away from reality.
I have no real deep takeways here - but my suspicion seems to be confirmed: bad shuffling seems to help to an extent. Also, one has to play quite a few games to actually figure out who’s the better player if the skill levels are any close.
There is one point that I still want to look at at some point in the future:
Improving the Game
Ligretto is influenced by a large amount of luck - is it possible to reduce this influence a bit by changing how points are allocated? The speed by which the table cards are laid down is largely influenced by the values of the cards that are in the stack. While the speed of the player obviously makes a difference, I am assuming that luck is the larger influence onto the win/lose result. I am also of the opinion that the way the points are counted (laid cards - 2*cards left on stack) is too punishing: The cards that are still on the stack are already ‘not laid’, it is quite extreme to subtract them twice from the (fewer) laid cards.
Now obvioulsy, one can always argue: ‘If you play enough games, the influence of chance will disappear, and the true skill will be the only difference.’ And while yes, this is clearly true, if would be nice if skill had a bigger impact, and you would not have to play a large number of games to find out who’s the faster/more reactive/better player.