Friday, February 5, 2021

Simulating Hoot Owl Hoot! in Python to find the best strategy

 Here's a board game simulation I wrote in Python to work out which strategy is the best to win the kid's game Hoot Owl Hoot!

My 5-year-old loves to play this board game made by Peaceable Kingdom where the players work cooperatively to move the owls along a path to the nest before running out of time. 

We were all playing one day and ended up debating on what the best strategy is to win - do you always move the piece that can go the farthest, or do you always move the piece in the back? It didn't seem like a clear answer at first - there are several game pieces and one moves on each turn to a color space chosen from the shuffled deck of cards, but they can jump over other pieces if there is one occupying the space they would otherwise land on. I thought it was best to move the one in the back so as to not strand one far behind the others (and therefore maximize the chance of getting to jump over spaces), while my wife thought you should always figure out which piece can go the farthest and move that one. 


Not satisfied with just not knowing the answer, I wrote a Python script that simulates the game. In this script only four owls are used (the way we usually play) and it doesn't bother including the sun chip - for my purposes it was sufficient to just see which strategy won in the fewest moves. 

The game is fairly simple to simulate - I made an array that holds the actual colors on the path which I copied from the game board, and there is an array of owl positions on that path. 


Each turn, a random color value is chosen and then some simple logic can move an owl forward to the next matching color while also checking for owls occupying the space that it could jump over and checking if it has reached the nest:


I wrote functions that would be used to evaluate the potential moves for each strategy by simply finding the rearmost owl:


and finding the longest potential move:


With those it was easy to make functions that would simulate an entire game played strictly by each strategy, and to make it really fair I had them both run simultaneously from the same random card deck sequence:


This got wrapped up in the main program that is run in a terminal and lets you choose the number of iterations to run and then gives the statistics on the result:


It turns out that the two strategies are remarkably close, despite leading to very different games each time, but if you run it through very many iterations, the longest move strategy tends to be best most of the time:



Here's the code. It's a bit messy with some nearly-duplicate functions since I built it up layer-by-layer and included a lot of stuff earlier on to print out the whole game board and detail each move to make sure the algorithms were correct before just running them without printouts to collect the statistics.