The Three Little Pigs
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Jesse, you asked me if I was in the meth business or the money business. Neither. I’m in the empire business (Walter White in Breaking Bad)
The game of pig has simple rules but complex strategies. It was described for the first time in 1945 by a magician called John Scarne. Playing the pig game is easy: each turn, a player repeatedly rolls a die until either a 1 is rolled or the player decides to hold:
- If the player rolls a 1, they score nothing and it becomes the next player’s turn
- If the player rolls any other number, it is added to their turn total and the player’s turn continues
- If a player chooses to hold, their turn total is added to their score, and it becomes the next player’s turn
The first player who reach at least 100 points is the winner. For example: you obtain a 3 and then decide to roll again, obtaining a 1. Your score is zero in this turn. Next player gets the sequence 3-4-6 and decides to hold, obtaining a score of 13 points in this turn.
Despite its simplicity, the pig game has a very complex and against-intuition optimal strategy. It was calculated in 2004 by Todd W. Neller and Clifton Presser from Gettysburg College of Pennsilvania with the help of computers.
To illustrate the game, I simulated three players (pigs) playing the pig game with three different strategies:
- The Coward pig, who only rolls the die a small number of times in every turn
- The Risky pig, who rolls the die a more times than the coward one
- The Ambitious pig, who tries to obtain in every turn more points than two others
I simulated several scenarios.
- Some favorable scenarios for Coward pig:
In first scenario, the Coward pig rolls the die between 1 and 5 times each round and wins if the Risky pig asumes an excessive level of risk (rolling each time between 10 and 15 times). Trying to obtain more than the Coward is a bad option for the Ambitious pig. Simulating this scenario 100 times gives victory to Coward a 51% of times (25% to Risky and 24% to Ambitious).
Second scenario puts closer Coward and Risky pigs (first one rolls the die between 4 and 7 times each round and second one between 6 and 9 times). Coward wins 54% of times (34% Risky and only 12% Ambitious).
Being coward seems to be a good strategy when you play against a reckless or when you are just a bit more conservative than a Risky one.
- Some favorable scenarios for Risky pig:
Rolling the die between 4 and 6 times each round seems to be a good option, even more when you are playing against a extremely conservative player who rolls no more than 3 times each time. Simulating 100 times these previous scenarios gives victory to Risky pig a 58% of times in first the case in which Coward rolls allways 1 and Risky 6 times each round (0% for Coward and only 42% form Ambitious) and 66% of times in the second one (only 5% to Coward and 29% to Ambitious).
Being Risky is a good strategy when you play against a chicken.
- Some favorable scenarios for Ambitious pig:
The Ambitious pig wins when two others turn into extremely coward and risky pigs as can be seen in the first scenario in which Ambitious wins 65% of the times (31% for Coward and 4% for Risky). Ambitious pig also wins when two others get closer and hit the die a small number of times (2 rolls the Coward and 4 rolls the Risky). In this scenario the Ambitious wins 58% of times (5% for Coward and 37% for Risky). By the way, these two scenarios sound very unreal.
Being ambitious seems to be dangerous but works well when you play against a crazy and a chicken or against very conservative players.
From my point of view, this is a good example to experiment with simulations, game strategies and xkcd style graphics.
The code:
require(ggplot2) require(extrafont) #Number of hits for Coward CowardLower=2 CowardUpper=2 #Number of hits for Risky RiskyLower=4 RiskyUpper=4 game=data.frame(ROUND=0, part.p1=0, part.p2=0, part.p3=0, Coward=0, Risky=0, Ambitious=0) while(max(game$Coward)<100 & max(game$Risky)<100 & max(game$Ambitious)<100) { #Coward Little Pig p1=sample(1:6,sample(CowardLower:CowardUpper,1), replace=TRUE) s1=min(min(p1-1),1)*sum(p1) #Risky Little Pig p2=sample(1:6,sample(RiskyLower:RiskyUpper,1), replace=TRUE) s2=min(min(p2-1),1)*sum(p2) #Ambitious Little Pig s3=0 repeat { p3=sample(1:6,1) s3=(p3+s3)*min(min(p3-1),1) if (p3==1|s3>max(s1,s2)) break } game[nrow(game)+1,]=c(max(game$ROUND)+1,s1,s2,s3,max(game$Coward)+s1,max(game$Risky)+s2,max(game$Ambitious)+s3) } opts=theme( panel.background = element_rect(fill="darkolivegreen1"), panel.border = element_rect(colour="black", fill=NA), axis.line = element_line(size = 0.5, colour = "black"), axis.ticks = element_line(colour="black"), panel.grid.major = element_line(colour="white", linetype = 1), panel.grid.minor = element_blank(), axis.text.y = element_text(colour="black"), axis.text.x = element_text(colour="black"), text = element_text(size=25, family="xkcd"), legend.key = element_blank(), legend.position = c(.2,.75), legend.background = element_blank(), plot.title = element_text(size = 50) ) ggplot(game, mapping=aes(x=game$ROUND, y=game$Coward)) + geom_line(color="red", size=1.5) + geom_line(aes(x=game$ROUND, y=game$Risky), color="blue", size=1.5) + geom_line(aes(x=game$ROUND, y=game$Ambitious), color="green4", size=1.5) + geom_point(aes(x=game$ROUND, y=game$Coward, colour="c1"), size=5.5) + geom_point(aes(x=game$ROUND, y=game$Risky, colour="c2"), size=5.5) + geom_point(aes(x=game$ROUND, y=game$Ambitious, colour="c3"), size=5.5) + ggtitle("THE THREE LITTLE PIGS") + xlab("ROUND") + ylab("SCORING") + geom_text(aes(max(game$ROUND), max(max(game$Coward, game$Risky, game$Ambitious)), hjust=1.2, family="xkcd", label="WINNER!"), size=10)+ geom_hline(yintercept=100, linetype=2, size=1)+ scale_y_continuous(breaks=seq(0, max(max(game$Coward, game$Risky, game$Ambitious))+10, 10))+ scale_x_continuous(breaks=seq(0, max(game$ROUND), 1))+ scale_colour_manual("", labels = c(paste("Coward: ", CowardLower, "-", CowardUpper, " hits", sep = ""), paste("Risky: ", RiskyLower, "-", RiskyUpper, " hits", sep = ""), "Ambitious"), breaks = c("c1", "c2", "c3"), values = c("red", "blue", "green4"))+ opts
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.