3
\$\begingroup\$

This is my first project, a short text-based game. Does this code follow common best practices?

Here is the code for the class file:

# create a class called chapter
class chapter(object):
    # create its __init__ method, to which the start chapter text is passed
    def __init__(self, start_chapter_text):
        # store it in a variable
        self.start_chapter_text = start_chapter_text

    # create a function to print it
    def print_start_chapter_text(self):
        # print it
        print(self.start_chapter_text)


# make a scene class
class scene(object):
    # create its init function to which the scene text, A list of choices, and the next scene are passed
    def __init__(self, scene_text, choice):
        self.scene_text = scene_text
        self.choices = choice

    # create the print_scene method, it prints the scene text
    def print_scene(self):
        # print it
        print(self.scene_text)

    # creat a get_choices method which gives you the choices
    def get_choices(self):
        # return it
        return self.choices

Here is the code for the game:

# import needed files
from classes import *


# create a method that gets the user's choice
def get_user_action():
    # get the choice and convert it to a number
    choice = int(input("enter your choice:> "))
    # return it
    return choice


# create an instance of chapter, call it chapter_1
chapter_1 = chapter("chapter 1, the escape")
# create an instance of chapter, call it chapter_2
chapter_2 = chapter("chapter2, the game of guess the password")
# create the choices for the first and second scene
choices_of_chapter_1 = "1: examin the scene more closely, 2: shout for help"
choices_2_of_chapter_1 = "1: read the note, 2: leave it"
# create the scenes, pass the constructer the scene text and the choices
scene_1_of_chapter_1 = scene(
    "you do not have a clue as to how you got here, you are standing in a dark coridoor, only lit by emergency lamps.",
    choices_of_chapter_1,
)
scene2_of_chapter_1 = scene(
    "you see a paper note lieing on the flore.",
    choices_2_of_chapter_1,
)
scene1_of_chapter_2 = scene(
    "you walk slowly in to the room, getting closer to the computer, you see that the computer askes for a password, you give it a try, after all, you got nothing better to do",
    None,
)
# print the text that start's chapter 1
chapter_1.print_start_chapter_text()
# print the first scene
scene_1_of_chapter_1.print_scene()
# print its choices
print(scene_1_of_chapter_1.get_choices())
# use a while loop for the game
while 1:
    # use a try block
    try:
        # get the user action
        action = get_user_action()
        # if it is = to 1
        if action == 1:
            # print scene 2 and it's choices
            scene2_of_chapter_1.print_scene()
            print(scene2_of_chapter_1.get_choices())
            # get the user action
            second_action = get_user_action()
            # if it = 1
            if second_action == 1:
                # print next to last scene
                print(
                    "you pick up the note and read it, it reads: welcome, are you reddy, player?, with a grinding sound, the wall infrunt of you moves away reveeling a room with a computer."
                )
                # start chapter 2
                chapter_2.print_start_chapter_text()
                # print the first scene of chapter 2
                scene1_of_chapter_2.print_scene()
                # ask for the password
                password = input("enter the password:> ")
                # if it is admin
                if password == "admin":
                    # player wins, print the win ending
                    print("you wone the game")
                    print(
                        'you here a voice cumming from an unseen sorce, the voice says: " I told you not to set the password to admin!", an other voice says: "let him go, we suck at building an escaperoom.'
                    )
                    print("you wone")
                    break
                # if the password is not admin

                else:
                    # player does not win, print the other ending
                    print(
                        "the last sound you here is the wall mooving back, seeling you in the space"
                    )
                    print("the end")
                    break
            # if action for scene2 of ch 1 is = 2
            elif second_action == 2:
                # print what happens
                print(
                    "you ignore the note, but nothing seems to happen, maybe you should read it?"
                )
        # if action for scene1 of ch 1 = 2
        elif action == 2:
            # print it
            print("you shout your lungs out, but nothing happens")
        # if not any of them
        else:
            print("your choice should be the number 1 or the number 2")
    # if we do not input a number
    except:
        # ask for a number
        print("enter a number")
\$\endgroup\$
2
  • \$\begingroup\$ Your Chapter class is actually intended to store state (scenes, actions and corresponding text), like Attack68's answer. It's not just (as written) a wrapper for one string start_chapter_text, and the print_start_chapter_text() method could have more Pythonically been written as a __str__() method that returns the relevant text, which the caller would then print. \$\endgroup\$
    – smci
    Commented May 18 at 1:33
  • \$\begingroup\$ In this case your entire state is just which scene of which cpater you're currently in; you don't have to track which objects you're carrying/using, supplies, weapons, money, food, hunger level etc. \$\endgroup\$
    – smci
    Commented May 18 at 1:36

2 Answers 2

3
\$\begingroup\$

The answer provided by @toolic is already very good.

I would add two comments.

Cyclomatic code complexity

In your main while loop you have a lot of nested if:else. In one case about 20 lines or so go by before you get to the elif that follows an if. Restructure this by taking sub-code into a method. It is better to have

if condition:
    do_this(*args)
    and_also_something_separate(*args)
else:
    do_that(*args)

def do_this(*args):
    ...

def and_also_something_separate(*args):
    ...
    
def do that(*args):
    ...

than

if condition:
    # lots of messy disconnected actions
else:
    # lots more lines of actions.

Data structure

Your data is almost better suited in a self contained object like a JSON dict. This would avoid the variable naming issue if you developed a standardised syntax for your game. For example, you have:

chapter_1 = chapter("chapter 1, the escape")
# create an instance of chapter, call it chapter_2
chapter_2 = chapter("chapter2, the game of guess the password")
# create the choices for the first and second scene
choices_of_chapter_1 = "1: examin the scene more closely, 2: shout for help"
choices_2_of_chapter_1 = "1: read the note, 2: leave it"
# create the scenes, pass the constructer the scene text and the choices
scene_1_of_chapter_1 = scene(
    "you do not have a clue as to how you got here, you are standing in a dark coridoor, only lit by emergency lamps.",
    choices_of_chapter_1,
)
scene2_of_chapter_1 = scene(
    "you see a paper note lieing on the flore.",
    choices_2_of_chapter_1,
)
scene1_of_chapter_2 = scene(
    "you walk slowly in to the room, getting closer to the computer, you see that the computer askes for a password, you give it a try, after all, you got nothing better to do",
    None,
)

I would have:

chapters = {
    1: {
        "title": "Chapter 1, The Escape",
        "scenes": {
            1: {
                "description": "You do not have a clue as to how you got here. You are standing in a dark corridor, only lit by emergency lamps.",
                "choices": {
                    1: "Examine the scene more closely.",
                    2: "Shout for help."
                }
            },
            2: {
                "description": "You see a paper note lying on the floor."
                "choices": {
                    1: "Read the note."
                    2: "Ignore the note."
                }
            }
    },
    2: {
        "title": "Chapter 2, The Game of Guess the Password",
        ...
    }
}  

Then you can access any part of your game as necessary with, for example,

chapters[1]["scenes"][2]["choices"]

This data structure also makes all of your classes redundant. Your classes do nothing other than store and index data which dicts can do better. And you do not need methods to print text. The print method works well for that provided you can index what you want it to print.

\$\endgroup\$
2
\$\begingroup\$

File name

This line implies that you named a file classes.py:

from classes import *

The file name is too generic. Give it a more meaningful name related to your game.


Class name

There is no need for object in the line below:

class chapter(object):

Also, it would be better to follow the PEP 8 naming convention for classes and capitalize the 1st letter:

class Chapter:

The same advice applies to the other class.


Comments

Comments like the following are not too meaningful:

# create a class called chapter

It would be better to use a docstring to describe what you mean by a chapter:

class Chapter:
    """ A chapter blah blah blah """

The comments can be omitted from the following function since you used a meaningful name for the function and print is self-explanatory:

# create a function to print it
def print_start_chapter_text(self):
    # print it
    print(self.start_chapter_text)

The same advice applies to the other comments in your class file as well as your main code file.


Spelling

There are several spelling mistakes in your code comments, input prompts and print messages. Use a spell-checker for your code. Here are a few:

flore
creat
wone
askes

For example, change:

"the last sound you here is the wall mooving back, seeling you in the space"

to:

"the last sound you hear is the wall moving back, sealing you in the space"

UI/UX

When running the code, the user should have the option of cleanly exiting the game. I can't even used the tried-and-true Ctrl-C to quit.


Long lines

You should break up your long lines of code into multiple lines.


Idioms

The following:

while 1:

is more idiomatic as:

while True:
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.