Part 3: Prettify#

In this section we’ll start making things prettier by wrapping text and adding colors and styles.

We’ll also make sure that the way we print things is consistent by always printing via our custom functions: header(), wrap(), write(), error(), or debug().

Part 3.1: Text wrapping#

In this section we’re going to add a wrap() function, which we’ll use to print paragraphs of text like place or item descriptions. We’ll both indent and wrap the text so that it looks nice.

Demo

A. At the top of adventure.py#

  1. [ ] import the textwrap module

  2. [ ] Add a global variable WIDTH and assign it the value 60 (or so, to taste).

  3. [ ] Add a global variable MARGIN and assign it to 2 or 3 (or so, to taste).

Code
 6import re
 7import textwrap
 8
 9WIDTH = 45
10
11MARGIN = 2
12
13DEBUG = False
14
15PLAYER = {

B. Define wrap()#

  1. [ ] Define a wrap() function which takes one argument text.

  2. [ ] For now, just print text in the function, so we can make sure it works.

C. Modify do_go(), at the end#

  1. [ ] Instead of calling print() to print the place description, call the wrap() function you just wrote.

Code
134    # print information about the new place
135    print(f"\n{new_place['name']}\n")
136    wrap(new_place["description"])
137

D. Wrap wrap()#

In this section we’ll call textwrap.fill() function to wrap a paragraph of text.

  1. [ ] Multiply a single space (" ") by MARGIN and assign it to the local variable margin (note that the two different cases).

  2. [ ] Remove the line where you previously printed text.

  3. [ ] Call the fill() function from the textwrap module and assign the result to the variable paragraph. Pass the arguments:

    • text

    • WIDTH

    • keyword argument initial_indent with the value margin

    • keyword argument subsequent_indent with the value margin

  4. [ ] Print paragraph.

Code
52def wrap(text):
53    """Print wrapped and indented text."""
54    margin = MARGIN * " "
55    # wrap the text
56    paragraph = textwrap.fill(
57        text,
58        WIDTH,
59        initial_indent=margin,
60        subsequent_indent=margin,
61    )
62
63    # print the wrapped text
64    print(paragraph)
65

Part 3.2: Colors#

In this section we’re going to use the console module to make our game more colorful.

A. Install console#

  1. [ ] Follow the instructions here to install.

Demo

B. At the top of adventure.py#

  1. [ ] Import fg, bg, and fx from console.

Code
6import re
7import textwrap
8
9from console import fg, bg, fx

C. Modify error(), debug(), other places…#

  1. In the places you want it, such as in the error() and debug() function, add colors and styles to your taste.

Code
68def error(message):
69    """Print an error message."""
70    print(f"{fg.red('! Error')} {message}\n")
71
72def debug(message):
73    """Print a debug message if in debug mode."""
74    if not DEBUG:
75        return
76    print(fg.lightblack(f"# {message}"))
77
140def main():
141    print("Welcome!")
142
143    while True:
144        debug(f"You are at: {PLAYER['place']}")
145
146        reply = input(fg.cyan("> ")).strip()
147        args = reply.split()

Part 3.3: Header and write functions#

In this section we’re going to write a header() function to print pretty headers and a write() function to print all other one-line messages.

Demo

A. Define write()#

In this section we’ll define a write() function that we’ll use to print non-wrapping messages to the player. This is to make sure that they’re all indented at the same level, or to add any extra formatting.

Code
74def write(text):
75    """Print an indented line of game text."""
76    print(MARGIN * " ", text, sep="")
77
  1. [ ] Write a function named: write with one parameter: text

  2. [ ] In the function: print MARGIN multiplied by a single space (" "), followed by text. You can do this as an f-string or pass the keyword argument sep with the value "" to avoid adding an extra space between them.

B. Define header()#

The header() function should style the title text using the fx, fg and/or bg objects, add any additional desired formatting, then print it by calling the write() function.

These steps are to add a blank line before and after the title and to make it bold, but you can change it to suit your taste.

Code
54def header(title):
55    """Print a header"""
56    print()
57    write(fx.bold(title))
58    print()
59
  1. [ ] Write a function named: header with one parameter: title

  2. [ ] In the function:

    • [ ] Print a blank line.

    • [ ] Use the bold method on the fx object to make title bold. (Or whatever other styles/colors you want.)

    • [ ] Pass the result as an argument to write().

    • [ ] Print a blank line.

C. Modify do_shop():#

Replace print() calls with header() and write() calls.

Code
88def do_shop():
89    """List the items for sale."""
90
91    header("Items for sale.")
92
93    for item in ITEMS.values():
94        write(f'{item["name"]:<13}  {item["description"]}')
95
96    print()
97
  1. [ ] When printing the title ("Items for sale") call header() instead of print().

  2. [ ] When printing the item name and description, change the call to the print() function to call the write() function instead.

D. Modify do_quit():#

Replace print() call with write() call.

  1. [ ] When printing any message (like "Goodbye") call write() instead of print().

Code
 98def do_quit():
 99    """Exit the game."""
100    write("Ok, goodbye.\n")
101    quit()
102

E. Modify do_go():#

Replace print() call with header() call.

  1. [ ] When printing the place name call header() instead of print().

Code
146    # print information about the new place
147    header(f"{new_place['name']}")
148    wrap(new_place["description"])
149