Ex 52 How to print the variable options to web after the description

loving this Gothon adventure story. I was wondering if anyone could help me with excercise 52.

There is this code in app.py

if request.method == "GET":
        if room_name:
            room = planisphere.load_room(room_name)
            return render_template("show_room.html", room=room)

and there is this code in planisphere.py

class Room(object):
    
    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.paths = {}
        self.response = {}

    def go(self, direction):
        return self.paths.get(direction, None)

    def add_paths(self, paths):
        self.paths.update(paths)#.update updates the dictionary

    def answer(self, response_to_user):
        return self.response.get(response_to_user, None)

    def generate_response(self, response):
        self.response.update(response)

#central corridor becomes a Room object from which you can run .add paths.
central_corridor = Room("Central Corridor", 

"""The Gothons of Planet Percal #25 have invaded your ship and destroyed your entire crew. 
You are the last surviving member and your last mission is to get the neutron destruct bomb 
from the Weapons Armory, put it in the bridge, and blow the ship up after getting into an 
escape pod.

You're running down the central corridor to the Weapons Armory when a Gothon jumps out, 
red scaly skin, dark grimy teeth, and evil clown costume flowing around his hate filled body. 
He's blocking the door to the Armory and about to pull a weapon to blast you. 
""")

central_corridor.add_paths({'shoot!': generic_death, 'dodge!': generic_death, 'tell a joke': laser_weapon_armory})

i was wondering,

what code would i need to get the webpage to print out the options to screen as variables, rather than write in the options statically as text after the description ?
currently in show_room.html there is only {{room.description}}, so I want to print to html screen for example the add_path variables specific to that room just after the description, so that the user knows what the options are.

{{ room.description }}
{{ room.options }}

How would i need to change the existing code to do this ?

Hey, I sent you an offline reply, but basically you’d need to add a .choice to each room, then list the paths and print the choices. You could make a .options() function in a room that does that. I recommend you first prototype what this should look like in the HTML so you know what you’re making.

oh so something like…

class Room(object):
    
    def __init__(self, name, description, options):
        self.name = name
        self.description = description
        self.options = options
        self.paths = {}
        self.response = {}

    def go(self, direction):
        return self.paths.get(direction, None)

    def add_paths(self, paths):
        self.paths.update(paths)
    
    def print_options(self, paths):
        self.paths(print("your options are :- ", paths.keys())) # hopefully prints the list of input options.
    # if I wanted to assign a number to each option, and allow that number to be pressed instead of typing out the text, i wonder how I could do that !? 
   

    def answer(self, response_to_user):
        return self.response.get(response_to_user, None)

    def generate_response(self, response):
        self.response.update(response)

central_corridor = Room("Central Corridor", 

"""The Gothons of Planet Percal #25 have invaded your ship and destroyed your entire crew. 
You are the last surviving member and your last mission is to get the neutron destruct bomb 
from the Weapons Armory, put it in the bridge, and blow the ship up after getting into an 
escape pod.

You're running down the central corridor to the Weapons Armory when a Gothon jumps out, 
red scaly skin, dark grimy teeth, and evil clown costume flowing around his hate filled body. 
He's blocking the door to the Armory and about to pull a weapon to blast you. 
""", {'shoot'!': generic_death, 'dodge!': generic_death, 'tell a joke': laser_weapon_armory})

central_corridor.add_paths(options)
central_corridor.options(options)

Maybe. I added code blocks so I could see what you’re doing, but it still isn’t formatted well. Remember to do this when you post code:

[code]
# paste code here
[/code]

So in your options you have self.paths() but paths is just a variable on self right? An attribute? and you’ve done this:

self.paths = {}

So that means it’s a dict. You can’t just call () on it. What you want to do is have any call to .options return what you need for the UI. Did you do the UI in HTML? I highly you have to do that first, or else I have no idea if you mean to show the paths people can take or the options or what you want them to see.

Do that, make the HTML work, post a screenshot of it working, then I can help you with the code.

I have an analogy for what you’re currently trying to do by attacking the code before the UI:

Let’s say you come to me and you go, “Zed I want my car to like make some noises when I push a button. Now, do you think the way I’ve ripped the engine block out and gutted the carpet will help?”

My reply would be, “What kind of noises? Like a horn? A music? Can you just go record a sample first before you go ripping the engine out?”

Make sense?

My show_room.html template is

{% extends "layout.html" %}
{% block content %}
<h1> {{ room.name }} </h1>
<pre>
{{ room.description }}
{{ room.options }}
</pre>
{% if room.name in ["death", "The End"] %}
<p><a href="/">Play Again?</a></p>
{% else %}
<p>
<form action="/game" method="POST">
- <input type="text" name="action"> <input type="SUBMIT">
</form>
</p>
{% endif %}
{% endblock %}

so what you have asked me to do is to print some text to screen in html below the description. A sample of what it should look like. Will do.

ps. I amended to

def print_options(self, paths):
        return print("your options are :- ", paths.keys())

i notice that MSVSCode is highlighting an error using variable before assignment for generic death here:-

[code]
“”",{‘shoot!’: generic_death, ‘dodge!’: generic_death, ‘tell a joke’: laser_weapon_armory})
central_corridor.add_paths(options)
central_corridor.options(options)
[\code]
I understand what it means, so I’ll have to figure out how to get around that.

So the room.options should be a list of strings with the options available. Now, print_options isn’t going to do anything, and this is a really weird line of code:

return print("your options are :- ", paths.keys())

That will return and print the options? But return is totally different from print. The print function is to just write text to the computer’s console, but return is to return a value to the calling function.

So, based on this I think you need to go take a break for a while. You’ve written quite a lot of code that doesn’t have this simple mistake, so that tells me your brain is super tired and anything you write today is probably going to be garbage. I actually try to limit my coding time to 6 hours a day for this very reason. Go take a break for a while, come back fresh and you’ll see how to do it.

:laughing: it is 1am here, guess it is time time to take a very long break :slight_smile:

a sample screenshot attached

image

However, this came from a simple approach to just adding some static text onto the end of the description:-

central_corridor = Room("Central Corridor", 

"""The Gothons of Planet Percal #25 have invaded your ship and destroyed your entire crew. 
You are the last surviving member and your last mission is to get the neutron destruct bomb 
from the Weapons Armory, put it in the bridge, and blow the ship up after getting into an 
escape pod.

You're running down the central corridor to the Weapons Armory when a Gothon jumps out, red scaly skin, dark grimy teeth, and evil clown costume flowing around his hate filled body. 
He's blocking the door to the Armory and about to pull a weapon to blast you. 
Do you
1.  "shoot!" him, Clint Eastwood quick draw style?
2.  "dodge!", or 3.  tell a joke"  """)

what would you say was the best way to do it to make use of existing options dictionary ?

Sheesh I’d be done if it were me! Do some markdown and put those long texts in a file and I think that’s better then trying to put that into code. Data always wins over code. Check out markdown:

Then you can save this to a file, load it off the file, convert it to markdown, and display the HTML.

I put this code in

dir_path = os.path.dirname(os.path.realpath(__file__))
print("dir_path", dir_path)
with open("C:\....\projects\gothonweb\gothonweb\central_corridor.txt", "r", encoding="utf-8") as input_file:
    text = input_file.read()
html = markdown.markdown(text)
central_corridor = Room("Central Corridor", html)

and got this error message… hmm

File “C:…\projects\gothonweb\gothonweb\planisphere.py”, line 29
with open(“C:…\projects\gothonweb\gothonweb\central_corridor.txt”,
“r”, encoding=“utf-8”) as input_file:
^
SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in positio
n 2-3: truncated \UXXXXXXXX escape

this is in the text file

Ah that’s an annoying error message. So you can drop the encoding=‘utf-8’ part and let it try to open. Also, on windows try “rb” instead of “r” and see if that helps. There’s also an option to open that says to just ignore errors:

https://docs.python.org/3/library/functions.html#open

Give errors=‘ignore’ and it should just ignore that. One thing that might have happened is you saved this file as a .txt file, but this text editor is setting the encoding on it to your native computer’s setting. See if you can force it to ASCII or utf-8 in the text editor. If not then the above will fix it.

Next, you have this "C:\....\projects\gothonweb\gothonweb\central_corridor.txt" You don’t have to give the full path. I’d put these text files in the same place as you’d put your templates, then you should be able to do:

open("templates/central_corridor.txt", "r", errors="ignore")

And that should make it work. Play with this and read the docs on open to figure it out.

25052020htmlcapture

it works, and shows up as html with the paragraph marks :slight_smile:

So close! Alright, first ditch the “”" marks from the file since that’s python. Then in the template render there’s a way to inject a “raw” string. What’s happening is the web framework is trying to help you keep things safe by escaping html, but you want the html, so read this:

https://jinja.palletsprojects.com/en/2.11.x/templates/#html-escaping

Which says you add |safe after variable in the ```{{ }}`` block to say it’s safe and doesn’t need escaping.

works like a dream :slight_smile:

image

You know that this game kind of reminds me of a game called Space Quest.

I was thinking how awesome it would be to actually do some graphics for this Gothon game. What would be a step in that direction ?

First, you need some graphics, so make up some with this:

http://grafx2.chez.com/

Or maybe this:

http://mtpaint.sourceforge.net/

And there’s even one’s that run in the browser. Save it as a .png, then in your game indicate whatever the pixel art is for that room. OR, keep it simple and just edit the markdown file and link it to the .png that’s sitting in your static directory (where you put css and js files).

A free service run by Zed A. Shaw for learncodethehardway.org.