Compsci 6/101, Spring 2011, Lab 11: Mad Libs

Use the Hand-In sheet and browse the code


Mad Libs were originally invented in the 1950's, and have appeared in numerous forms over the years (see wikipedia entry).
During today's lab, we'll be playing Mad Libs. This is a word game in which the player supplies words or phrases that fit various descriptions, and these words are then used in a story, often to comedic effect. Because the name Mad Lib is copyrighted, we'll use the name Tag-A-Story (you can call these Mad Libs yourself).

For example, suppose the tag-a-story is as follows.

The lab in Compsci 6 is <adjective> and I <emotive verb> it.

With this tag-a-story we might get any of the substitution stories below:

The lab in Compsci 6 is terrible and I love it.
The lab in Compsci 6 is long and I crave it.
The lab in Compsci 6 is squeamish and I despise it.
You'll be using one tag-a-story to develop and debug your program, then you'll be able to use any of the stories submitted by students in generating new stories. Note that words/phrases that will be replaced are delimited by angle-brackets: < and > as shown. We call these delimited words/phrases tags in this lab.

Start out by snarfing the code for this lab, or looking at the code directory.

There are five conceptual parts to this lab.

  1. Reading the tag-a-story template file and extracting the tags from it (in the order they appear).

  2. Substituting user-entered (first) and then auto-generated (later) words/phrases for each tag read so that a story can be auto-generated --- you'll essentially replace each tag by an auto-generated substitute.

  3. Create a dictionary of substitutions for each tag by reading the file word_lists.txt whose format is described below.

  4. Print the auto-generated story with a specified line-width, e.g., 50 characters per line or 80 per line and so on.

  5. (if time) Allow the user to choose a tag-a-story template from the web and/or allow the user to substitute her own replacements for each tag rather than having the substitutions auto-generated.

Complete the lab by following the steps below. Each step is accompanied by questions you should answer on the handin page -- be sure to answer these questions!

  1. First you'll add code to the function do_mad_lib so that the user can choose a replacement for each tag in the list all_tags. When you snarf and run the program at first, it prints this as the value of the local variable all_tags in do_mad_lib:
     ['adjective' 'food']
    
    You should write code so that a new list is created and assigned to the local variable subs that replaces each tag with a user-entered response. You can do this with a list comprehension by calling the function get_word_from_user with each tag as a parameter. When you've created this list and printed both all_tags and and the new list subs you're ready for step two.

    Handin Questions

  2. Create a string using the list subs , the string template and the string format operator % by adding this single line and printing the value of story.
       story = template % tuple(subs)
    

    Here you are using the % operator to do some string formatting. Given a string story that contains some "%s" substrings within it, and given a tuple tup with the same number of elements as there are "%s"'s in story, the expression story % tup substitutes each element of tup into story for the corresponding instance of "%s". To make this concrete, the expression

    "Insert something %s and something else %s" % ("here", "over here")
    creates the string "Insert something here and something else over here".

    Handin Questions

  3. Entering a phrase for each tag is time-consuming and auto-generated stories can be fun. To do this, we'll need a way to supply words that match a given description. This is supplied for you in the file word_lists.txt, but we need to parse it into a useful format.

    Complete the function read_tagstore which will add tags and replacements to a dictionary and return it. In the dictionary keys are strings representing tags (word/phrase), and the key's corresponding value is a lists of strings that will be substituted for the key. For example:

    adjective: awesome, boring, stupid, amazing, fantastic, confusing, silly, big, yellow
    animal: dog, cat, human, lion, pony, squirrel
    
    
    Note that each tag is separated from replacements by a colon character and replacements are comma-separated (you'll need to use the string .split method twice). In the file word_lists.txt a tag can occur multiple times, e.g., on different lines. This means if the key is already in the dictionary you'll need to add strings to its list (use the list .extend method).

    When you've read the file and created the dictionary, be sure to print it to verify that you read the file correctly, then remove or comment-out the print statements.

    Handin Questions

  4. To test that the dictionary was created properly you can replace the function get_word_from_user() you used in the first part of lab with get_word_from_computer() which uses the global dictionary _tagstore. Make that change in do_mad_lib. Then make the function used to get replacements for tags a parameter passed to do_mad_lib. Add a new parameter to the function, named tag_getter, which will be the function used to get words to replace each tag in the story -- pass the argument get_word_from_computer (no parentheses) when you call do_mad_lib.

    This kind of modification (changing prevously written code to be more general, extensible, efficient, or elegant) is called a "refactoring." Software engineers refactor code all the time, because it makes code easier to use in the future.

    Handin Questions

  5. Rather than printing the story on a single line, complete the function print_out that has been started in the program. You'll need to add two lines, though you can add more. You'll also need to change the line print word so that it prints a word and a space and stays on the same line. Each line you add updates the value of local variable curr_len so that it represents the number of characters printed on the current line. If you update the value twice, the function should work correctly -- call it from do_mad_lib to print the completed story. The idea is to print each word in story one-at-a-time (with a space after it), but if printing the word would cause more than line_width characters to be printed on a line, start a new line.

    Handin Questions

  6. You should write your own tag-a-story/Mad Lib and upload it to this site: http://www.cs.duke.edu/csed/tag-a-story/upload/. Pick a category and upload your file. You can verify that the file was uploaded by running the program URLreader.py and choose the file you uploaded.

  7. If there is extra time, try to use the combine the functionality of the URLreader.py module with the MadLibs.py module to generate a story from a URL.