Context

When the time came to choose a programming language, I chose Python because the name was inspired by the inimitable Monty Python. As a Pythonist, I also used Monty Python as an inspiration when I wanted to learn the Python programming language. I started working on the (now paused) RPG based on the Monty Python holy grail movie project. I learned to play around with the pygame module as well as a bit about the objected-oriented aspects of Python.

I had noted down a long time back that I wanted to use the contents from the remarkable website MontyPython.net in some application or the other. So when I saw a hangman game implementation in Python on the Kite Youtube channel, I immediately thought that I should build a hangman, but with a Monty Python theme.

This blog entry is the story of how that came about.

Preparing the Pythoraus

Warning: Pythoraus is a word I just made up

I wanted to say a Python Thesaurus, the word list that provides a pool for the game to pick words from. But, given that it would be silly to prepare a world list, I decided that it should be a quote list. The MontyPython.Net had the scripts, so all I needed now were web scraping tools. I chose BeautifulSoup because I liked the name (you need to decide based on some condition).

I quickly realized that making sense of the quotes from the entire Monty Python content (several movies and several seasons of the show) would be daunting. So I decided to stick to the Holy Grail movie script. Another reason tied my hands too. I found it difficult to narrow down on the popular quotes (to avoid using every dialogue or description). This is when I noticed that the website admin had done something awesome: add audio clips to famous quotes, but only for the Holy Grail movie. So I decided to focus only on those quotes that have been given an audio file. I later added a few more quotes manually into the list generated, but, web scraping using BeautifulSoup did a great job. To make sure everything went smooth, I had to circumvent problems through some quirks, but overall, I got a nice set of quotes.

The sources used are as follows

sources = [requests.get('https://montypython.net/grailmm1.php').text,
           requests.get('https://montypython.net/grailmm2.php').text,
           requests.get('https://montypython.net/grailmm3.php').text]

The following code gets the quotes into a list.

monty_python_quotes = []
quote = None
for source in sources:
    soup = BeautifulSoup(source, 'lxml')
    for aa in soup.find_all('a'):
        if 'href' in aa.attrs: #looking for only those which are hyperlinks
            if '.wav' in  aa.attrs['href']: # We are only looking for those quotes which have an associated sound file
                if len(aa.contents) > 1:
                    quote = aa.contents[0]
                else:
                     quote = aa.contents

        if quote is None:
            pass
        else:
             if isinstance(quote, list):
                    if isinstance(quote[0], bs4.element.NavigableString): # It was observed that all the valid quotes were of this type
                        if len(quote[0].split(' ')) > 1 : # To avoid single word quotes that were mostly useless.
                            monty_python_quotes.append(quote[0])

# There were several quotes that were duplicated.
# The following trick of converting the list into dictionary and back helped to remove them                            
monty_python_quotes = list(dict.fromkeys(monty_python_quotes))

Hangman Display - Holy Grail Style

When I saw the terminal avatar of hangman, I felt that it is too generic and I needed something that captures the spirit of Monty Python. So what better than the Black Knight?

So I created a series of black knight terminal avatar in the same way he loses limbs in the movie. One arm, then the next arm, one leg and then both legs.

def display_black_knight(state):
    knight = [
                """
            "You lost. I'm off to cross the bridge"


                  O
                  |



                """,
                """
            "You loose both your legs. I won't call it a draw"
                  _
                 | |
                  O
                  |



                """,
                """
            "A single-legged knight?"
                  _
                 | |
                  O
                  |
                  |
                 /

                """,
                """
            "Now you got no hands"
                  _
                 | |
                  O
                  |
                  |
                 / \\

                """,
                """
            "Ouch! You lose your sword hand"
                  _
                 | |
                  O
                  |\\
                  |
                 / \\

                """,
                """
            "You are the Black knight"
                  _
                 | |
                  O
                \\/|\\
                  |
                 / \\

                """
    ]
    return knight[state]

Awesome, isn't it? Well, at least I feel so. And I also added quotes on top.

The game provides the player with 5 guesses (if one feels an expert, they can go for the expert model with 3 chances). You can get the rest of the code here in the github repository.

And below is the case when I go through all stages of the black knight state and lose:

And here I win.

Final Remarks

I took some time to write this blog entry because I hoped to finish an ipython-widget-based version of the game (hence everyone can play the game using binder). But it got stuck in some technicalities (and I still have to figure out if everything I want to do will work well with the widgets). So until I get that up and running, you have no other choice but to download the code from the repository and play the game.

Have fun.