Editor

Word Story Game in Python

Beginner · Games · about 30 minutes to build · 117 lines

It asks you for words such as an adjective, an animal and a number without showing the story, then prints the story with your words in it.

The program

Press Run and answer its questions in the box that appears under the code.

word_story_game.py
"""Word story game: type words without seeing the story, then read the silly result."""
import random
import textwrap
LINE_WIDTH = 60
# A short explanation shown for each kind of word.
HINTS = {
"adjective": "a describing word, like fluffy",
"noun": "a thing, like bicycle",
"plural noun": "more than one thing, like socks",
"verb": "an action, like jump",
"verb ending in -ing": "like dancing",
"animal": "like giraffe",
"food": "like pancakes",
"name": "a person's name",
"place": "like the library",
"number": "a whole number",
}
# Each story lists its blanks in the order they are asked: (key, kind of word).
STORIES = [
{
"title": "The School Trip",
"blanks": [("place", "place"), ("teacher", "name"), ("adj1", "adjective"),
("animal", "animal"), ("moving", "verb ending in -ing"),
("count", "number"), ("things", "plural noun"), ("food", "food"),
("adj2", "adjective")],
"text": "Last week our class went on a trip to {place}. Our teacher, "
"{teacher}, promised it would be {adj1}. As soon as we arrived, "
"a wild {animal} came {moving} past us, carrying {count} {things}. "
"Everyone screamed except {teacher}, who calmly offered it some "
"{food}. All in all, it was a very {adj2} day.",
},
{
"title": "My Robot Helper",
"blanks": [("count", "number"), ("things", "plural noun"), ("adj1", "adjective"),
("thing", "noun"), ("robot", "name"), ("food", "food"),
("moving", "verb ending in -ing"), ("action", "verb"),
("place", "place")],
"text": "For my birthday I built a robot from {count} old {things} and one "
"{adj1} {thing}. I named it {robot}. Every morning {robot} makes "
"me {food} and then goes {moving} around the kitchen. Yesterday "
"it tried to {action} the cat, so now the cat lives in {place}.",
},
{
"title": "The Big Match",
"blanks": [("adj1", "adjective"), ("place", "place"), ("animal", "animal"),
("player", "name"), ("thing", "noun"), ("things", "plural noun"),
("food", "food"), ("moving", "verb ending in -ing")],
"text": "The final of the {adj1} cup was played in {place}, with a "
"nervous {animal} as our mascot. In the last minute, {player} "
"kicked the {thing} so hard that it flew over the {things} and "
"landed in a bowl of {food}. The whole crowd started {moving}, "
"and we won the cup.",
},
]
def ask_word(kind):
"""Ask for one word of the given kind until the answer looks right."""
while True:
word = input(f"{kind.capitalize()} ({HINTS[kind]}): ").strip()
if kind == "number":
if word.isdecimal():
return word
print(" Please type a whole number, like 7.")
elif word and all(ch.isalpha() or ch in " '-." for ch in word):
return word
else:
print(" Please type a word (letters only).")
def play_story(story):
"""Collect the words for one story, then print the finished story."""
print(f"\nFill in {len(story['blanks'])} words for a story. No peeking.\n")
answers = {}
for key, kind in story["blanks"]:
answers[key] = ask_word(kind)
finished = story["text"].format(**answers)
print(f"\n--- {story['title']} ---")
print(textwrap.fill(finished, width=LINE_WIDTH))
def choose_story():
"""Show the menu and return a story, or None when the player quits."""
while True:
print("\nStories:")
for number, story in enumerate(STORIES, start=1):
print(f" {number}. {story['title']}")
print(" R. Surprise me")
print(" Q. Quit")
choice = input("Choose a story: ").strip().lower()
if choice == "q":
return None
if choice == "r":
return random.choice(STORIES)
if choice.isdecimal() and 1 <= int(choice) <= len(STORIES):
return STORIES[int(choice) - 1]
print(f" Please type a number from 1 to {len(STORIES)}, R or Q.")
def main():
"""Play stories until the player quits."""
print("=== Word Story Game ===")
while True:
story = choose_story()
if story is None:
break
play_story(story)
print("Goodbye.")
if __name__ == "__main__":
main()

Open it in the full editor to save it, share it and keep building.

Sample run

What the program printed, and what was typed (in yellow).

=== Word Story Game ===

Stories:
  1. The School Trip
  2. My Robot Helper
  3. The Big Match
  R. Surprise me
  Q. Quit
Choose a story: 1

Fill in 9 words for a story. No peeking.

Place (like the library): the moon
Name (a person's name): Mr. Patel
Adjective (a describing word, like fluffy): sticky
Animal (like giraffe): penguin
Verb ending in -ing (like dancing): 
  Please type a word (letters only).
Verb ending in -ing (like dancing): skating
Number (a whole number): a dozen
  Please type a whole number, like 7.
Number (a whole number): 12
Plural noun (more than one thing, like socks): umbrellas
Food (like pancakes): spaghetti
Adjective (a describing word, like fluffy): noisy

--- The School Trip ---
Last week our class went on a trip to the moon. Our teacher,
Mr. Patel, promised it would be sticky. As soon as we
arrived, a wild penguin came skating past us, carrying 12
umbrellas. Everyone screamed except Mr. Patel, who calmly
offered it some spaghetti. All in all, it was a very noisy
day.

Stories:
  1. The School Trip
  2. My Robot Helper
  3. The Big Match
  R. Surprise me
  Q. Quit
Choose a story: q
Goodbye.

How it is built

1. Hints for each kind of word

Not everyone remembers what an adjective is, so every prompt comes with a short example from this dictionary.

HINTS = {
    "adjective": "a describing word, like fluffy",
    "noun": "a thing, like bicycle",
    "plural noun": "more than one thing, like socks",
    "verb": "an action, like jump",
    "verb ending in -ing": "like dancing",
    "animal": "like giraffe",
    "food": "like pancakes",
    "name": "a person's name",
    "place": "like the library",
    "number": "a whole number",
}

2. A story as data

Each blank has a key and a kind of word. The key matches a {placeholder} in the text, so {teacher} can appear twice in the story but is asked for once.

STORIES = [
    {
        "title": "The School Trip",
        "blanks": [("place", "place"), ("teacher", "name"), ("adj1", "adjective"),
                   ("animal", "animal"), ("moving", "verb ending in -ing"),
                   ("count", "number"), ("things", "plural noun"), ("food", "food"),
                   ("adj2", "adjective")],
        "text": "Last week our class went on a trip to {place}. Our teacher, "
                "{teacher}, promised it would be {adj1}. As soon as we arrived, "
                "a wild {animal} came {moving} past us, carrying {count} {things}. "
                "Everyone screamed except {teacher}, who calmly offered it some "
                "{food}. All in all, it was a very {adj2} day.",
    },

3. Checking a word

A number must be digits. Other words may have letters, spaces, hyphens, apostrophes and full stops, so Mr. Patel and ice-cream both work, and an empty answer is asked again.

def ask_word(kind):
    """Ask for one word of the given kind until the answer looks right."""
    while True:
        word = input(f"{kind.capitalize()} ({HINTS[kind]}): ").strip()
        if kind == "number":
            if word.isdecimal():
                return word
            print("  Please type a whole number, like 7.")
        elif word and all(ch.isalpha() or ch in " '-." for ch in word):
            return word
        else:
            print("  Please type a word (letters only).")

4. Filling in the story

story["text"].format(**answers) puts each answer where its key appears, and textwrap.fill breaks the story into lines of at most 60 characters.

def play_story(story):
    """Collect the words for one story, then print the finished story."""
    print(f"\nFill in {len(story['blanks'])} words for a story. No peeking.\n")
    answers = {}
    for key, kind in story["blanks"]:
        answers[key] = ask_word(kind)

    finished = story["text"].format(**answers)
    print(f"\n--- {story['title']} ---")
    print(textwrap.fill(finished, width=LINE_WIDTH))

5. The story menu

The menu takes a story number, R for a random story or Q to quit, and returns None to tell main() the player is done.

def choose_story():
    """Show the menu and return a story, or None when the player quits."""
    while True:
        print("\nStories:")
        for number, story in enumerate(STORIES, start=1):
            print(f"  {number}. {story['title']}")
        print("  R. Surprise me")
        print("  Q. Quit")
        choice = input("Choose a story: ").strip().lower()
        if choice == "q":
            return None
        if choice == "r":
            return random.choice(STORIES)
        if choice.isdecimal() and 1 <= int(choice) <= len(STORIES):
            return STORIES[int(choice) - 1]
        print(f"  Please type a number from 1 to {len(STORIES)}, R or Q.")

Make it bigger

  • Write your own story: add a dictionary to STORIES with a title, blanks and text.
  • Save each finished story to a text file to read later.
  • Ask for the blanks in a random order so the questions give fewer clues about the story.
  • Check the words more closely, such as asking again when a verb ending in -ing does not end with ing.

What it practises