Ex36 Game Complexity and Questions

Hi all, my first time posting here. I’m looking forward to interacting with everyone. So, I’m working on my game for exercise 36. I’m coming up on the end of it, and wanted to share with a few questions/concerns:

-I feel like the game is more text-intensive than code-intensive. While it was amusing to write, I’m wondering what kind of ideas you might have for increasing the complexity of the code and structure
-I initially wanted to use the car() function as something reusable (basically any time you move between locations), but then I realized I didn’t know how to soft code it so it could wind you up at somewhere other than hotel()
-I like that I have the global DIPL, yuan, and list, and that I have an object always being passed between functions, but with the list especially, I just don’t know how to integrate it more into the game
-The last room or two I want to turn into a kind of classic battle with the final boss, using DIPL as HP. No idea how to do that yet; I’m still looking into how to make weapons, give them strength, use random codes to determine success of strikes, etc. If anyone can point me to somewhere I can read up on that, I’d appreciate it!

Here goes (I hope this pastes in properly):

import random
DIPL = 0
INV = []
yuan = 10000

def check(DIPL):
    if DIPL >= 1000:
        print("Diplomacy: ", DIPL)
        print("You win! You collected: ")
        print(INV)
        exit(0)
    elif DIPL < 1000:
        print("Diplomacy: ", DIPL)
        return
    else:
        exit(0)

#def znh1(obj):
    

def zhongnanhai(obj):
    global DIPL
    global yuan
    check(DIPL)
    input()
    print("""As the car pulls through the front gate, two stoic guards
in green PLA uniforms posted on pedestals on either side, the
door next to you clicks unlocked. You get out and the car backs away,
the gate slamming shut.""")
    input()
    print("""Green tiled roofs over rust red walls stretch in all directions
around you: countless, identical rooms. Nobody is around, nothing moves.
You realize the twenty closest rooms have numbers posted over the doors,
so you decide to try one of them.""")

    while True:
        room = input("> ")
        if room == "1":
            print("Empty, dusty, cobwebs and broken tiles. Very CCP.")
        elif room == "2":
            print("""Rows and rows of broken stone lions, the balls
removed from their mouths. A repository of entrances past.""")
        elif room == "3":
            print("""The walls are papered with yellowing posters of
Mao. Listen to the Party, do what the Chairman says. Happy, happy, happy.
See how much grain we have? We never go hungry.""")
        elif room == "4":
            print("""A young woman, hair unwashed, sits at a rickety desk
littered with paper, red kerchiefs in cheap plastic envelopes,
and a yellowing, cold cup of tea. She is staring at her phone intensely
and does not seem to notice you. You take a kerchief before leaving.""")
            INV.append("red kerchief")
            DIPL = DIPL + 2
        elif room == "5":
            print("""This room is full of sound which, oddly, you couldn't
hear at all before you entered the door. Staticky speakers, enthusiastic but
weirdly monotone shouting, barked syllables. It is mollifying, frightening,
and obnoxious all at the same time.""")
        elif room == "6":
            print("""This is some sort of camera workshop. Dozens of
children sit crosslegged, holding screwdrivers from eyeglass repair kits,
determinedly assembling and disassembling "public security" cameras into
their consituent thousands of parts. One of them looks at you before
standing up, angrily, the screwdriver held like a weapon. It sounds like
he says "America" as he walks toward you, barefoot. You make like a tree.""")
            DIPL = DIPL - 1
        elif room == "7":
            print("""Instant cloud of cigarette smoke. Goons, a mah jongg
game. One of them stands up, a thick rope of gold around his neck, and
you feel a flash of pain in the back of your head...""")
            DIPL = DIPL - 7
            input()
            wake(obj)
        elif room == "8":
            print("""You remember reading that 8 is a lucky number for Chinese.
Unforunately, the same is not true for you. A woman sits at a plastic desk
and starts handing you forms, yelling "sign, sign!" and chopping them with
her stamp. "Money, money!" She indicates values on the forms with aggressive
finger jabs: 150 yuan, 75 yuan, 83 yuan. Death by a thousand cuts. Pay up, bud.""")
            yuan = (yuan - 150 - 75 - 83)
        elif room == "9":
            print("""The number 9 is a pun in Chinese--it means long. They like
to say it alludes to how long one will live, but in this case it is
for how long the "line" is. This room is packed with people, crowding
a desk at the back of the room that you can barely see, with no semblance of order.
Getting there is a long, long ways away.""")
            DIPL = DIPL - 2
        elif room == "10" and "red kerchief" in INV:
            print("""A steely guard stands blocking a door, but when he sees
your red kerchief, he steps aside.""")
            znh1(obj)
        elif room == "10":
            print("A steely guard stands blocking a door, staring you down.")
        elif room == "11":
            print("""A round table crowded with cards, peanut shells, bottles
of beer, cigarette butts. Rowdy, pink-faced, mid-level CPC placeholders
wave you over, jolly, loud. You drink with them, many back pats are exchanged.
Long discourses are given, none of which you understand.""")
            DIPL = DIPL + 40
        elif room == "12":
            print("""An empty room. You'd think they would be more efficient
with their real estate, right?""")
        elif room == "13":
            print("A pile of coats on the floor.")
            INV.append("random coat")
        elif room == "14":
            print("There's a... there's a bunch of bicycles in here?")
        elif room == "15":
            print("""You see an array of television screens long the walls. On
each is playing, on loop, recordings... of you. Recordings of you coming out of
the airport, you walking through the lobby of your hotel, and you, standing in
room 15, watching recordings of you.""")
            DIPL = DIPL + 15
        elif room == "16":
            print("""\"Mister! Mister!" That voice again. You feel a pair of hands
on your back, sliding around to your stomach.""")
            input()
            if obj == "fake passport":
                print("""\"I'm so sorry mister, I meant to give this back." You feel
your passport slide into your pocket. So it was her! When you turn around to look,
though, nobody is there.""")
                obj = "damaged passport"
            else:
                print("Oh, oh my.")
                DIPL = DIPL + 4
        elif room == "17":
            print("请勿入内")
        elif room == "18":
            print("This is a... it's a... subway station? In the president's residence?")
            yuan = yuan - 1
            subway(obj)
        elif room == "19":
            print("""Karaoke, enough said. Pink faced CCP. Sketchy, glittery women. Hours of
your life, gone, gone for good. You will never unhear the singing.""")
            DIPL = DIPL + 3
        elif room == "20":
            print("Boxes and boxes of old Taiwanese flags. You take one and get the hell out.")
            INV.append("Taiwanese flag")
        else:
            print("Is the pollution getting to you? That's not one of the rooms.")


def room(obj):
    global DIPL
    global yuan
    check(DIPL)
    input()
    print("""You walk, at long last, into your hotel room. There's a
stale smell of cigarette smoke and a pair of cardboard slippers
wrapped in plastic on the floor next to the bed. You put your
key card on the desk next to the ash tray and lay down, the
sheet bleached stiff and the mattress completely unbending. You
immediately fall asleep.""")
    input()
    wake(obj)

def wake(obj):
    global DIPL
    global yuan
    for x in range(1):
        sleep = random.randint(6,10)
    print(f"""You awaken suddenly, mouth dry, head thick, hazy light
leaking in through the dirty window. When you sit up and look at the
clock on the desk, your heart skips a beat... it's already {sleep} o'clock.
Shit, you overslept!""")
    DIPL = DIPL - sleep
    input()
    check(DIPL)
    input()
    print("""You shower, piss, and shave as quick as you can, then rush down
to the lobby. The woman at the desk (same one?) comes up to you. "Mister,
there is a car for you." You follow her out the front door, but as you get
into the black car that's waiting, she holds out her hand, soft palm and the
undersides of red-painted nails toward you. How much do you tip her?""")
    tip = input("> ")

    if tip.isdigit():
        if int(tip) in range (0, 100):
            print(f"""She lowers her hand, leaving the {tip} yuan dangling from
your fingers, and goes back into the hotel, the tight jacket sliding against her
back.""")
            DIPL = DIPL + 1
            yuan = yuan - int(tip)
            input()
            zhongnanhai(obj)
        elif int(tip) in range(100, 1001):
            print(f"""She takes the {tip} yuan from you without saying a word,
turns, and goes back into the hotel.""")
            DIPL = DIPL + 2
            yuan = yuan - int(tip)
            input()
            zhongnanhai(obj)
        else:
            print(f"""Smooth move. She takes the {tip} yuan from you and presses
a small paper into your hand, then turns and walks back into the hotel. When you
look at the paper, you see it's a note with "<3" and a phone number written
on it.""")
            DIPL = DIPL + 3
            yuan = yuan - int(tip)
            INV.append("<3 note")
            input()
            zhongnanhai(obj)
    else:
        print("""She stares at you long and hard before turning slowly and
going back into the hotel.""")
        DIPL = DIPL + 2
        input()
        zhongnanhai(obj)

def hotel(obj):
    global DIPL
    global yuan
    check(DIPL)
    input()
    print("""As you finally walk through the brass-rimmed glass
doors of your hotel, a sense of calm envelops you. Nearly
24 hours after departing, you will finally get some rest.
A high-gloss, white marble floor stretches between you and
the mahogany, gold filmaneted front desk. Elegant, hardwood
tables flank either side of the lobby.""")
    input()
    print("""You approach the desk, your footsteps ricocheting
from the walls. A tight-suited, perfectly made up young woman seems
to rise from nowhere. You reach in your pocket to take your passport
and slide it across the gleaming surface of the desk. She pulls it
toward herself with a leather-gloved hand and flips it open to the
first page.""")
    input()

    if obj == "fake passport":
        print("""She then pages slowly through the whole booklet,
picking it up, with a slight frown flickering across her face.
"Sir, we can only accept genuine documents.\"""")
        INV.append("fake passport")
        input()
        print("""Damn! Either that girl, or someone on the
subway switched out your passport. You see a bellboy, with
a very large head and no neck, walking menacingly toward you.
You then remember the 10,000 yuan your boss gave you. How
much do you give her?""")
        bribe = input("> ")

        if bribe.isdigit():
            if int(bribe) in range(0, 2001):
                print("""No good, no good my friend. You'd better study exchange
rates. Though, the only exchange you're going to be doing
for a while is converting number of punches to days of pain.""")
                DIPL = DIPL - 25
                yuan = yuan - int(bribe)
                keycard = "key card"
                INV.append(keycard)
                input()
                room(obj)
            else:
                print(f"""{bribe} yuan, good call. She thumbs the edges of the bills,
counting to herself in whispers. Then she takes a key card
from below the desk, hands it to you, and the bellboy leads
you to your room.""")
                DIPL = DIPL + 4
                yuan = yuan - int(bribe)
                keycard = "key card"
                INV.append(keycard)
                input()
                room(obj)
        else:
            print("""No good, no good my friend. You'd better study exchange
rates. Though, the only exchange you're going to be doing
for a while is converting number of punches to days of pain.""")
            DIPL = DIPL - 23
            yuan = yuan = int(bribe)
            keycard = "key card"
            INV.append(keycard)
            input()
            room(obj)

    else:
        print("""She then pages slowly through the whole booklet,
before reaching behind the desk and tapping on a keyboard you can't
see. She takes a key card from below the desk, hands it to you,
and the bellboy leads you to your room.""")
        DIPL = DIPL + 1
        keycard = "key card"
        INV.append(keycard)
        input()
        room(obj)

def seedyhotel(obj):
    global DIPL
    check(DIPL)
    input()
    print("""She leads you through a door you didn't notice until
you are walking through it, a faded red square of paper stuck hanging
at eye level by a piece of tape. Upstairs, she turns toward you and
pulls you by both hands into a small room. Do you resist?""")
    fed = False

    react = input("> ")

    while True:
        if "yes" in react and not fed:
            print("""You manage to break free and run back down the stairs,
frustrated cries of "Mister!" getting fainter behind you. In the
alleys, steam drifts from stacks of bamboo bun trays and salted
pork legs hang from the bars on windows. Eventually, you get a
taxi back to your hotel.""")
            DIPL = DIPL - 1
            fed = False
            input()
            hotel(obj)
        elif "no" in react or fed:
            print(f"""She guides you to the bed, and what you thought was
going to happen, happens. As you clean up, she looks at you sheepishly:
"Mister, I'm sorry." She squats on the floor to take a {obj} from
your pants pocket (when did she switch your passport??) and gives
you your real, but still damaged, passport back.""")
            input()
            print(""""Mister, I hope I can help you more in the future."
She walks with you downstairs and through the alleys, steam drifting
from stacks of bamboo bun trays and salted pork legs hanging from the
bars on windows. Eventually, you get to a street where she finds
you a taxi to your hotel.""")
            DIPL = DIPL + 6
            fed = True
            input()
            hotel("damaged passport")
        else:
            print("It doesn't matter.")
            fed = True
            DIPL = DIPL -4
            input()

def subway(obj):
    global DIPL
    check(DIPL)
    input()
    print("""Three cars pass before you're able to board. Thirty grannies
cut in front of you... three hundred? The shouting is unbearable.
There are no seats, no space to bend your knees to sit if there were.
An hour later, you're swept off, swept up the stairs to the street.""")
    DIPL = DIPL - 2
    input()
    hotel(obj)


def subway2(obj):
    global DIPL
    check(DIPL)
    input()
    print("""She takes you to the subway, an unbearable crush of people.
There are no seats, no space to bend your knees to sit if there were.
She holds your arm the whole time, her fingers sweaty, grip loosening.""")
    print("Do you stay with her or escape?")
    failtry = False
    choice = input("> ")

    while True:
        if "stay" in choice or failtry:
            print("""An hour later, she leads you off the car. You take
a dark, narrow stairway at the back of the subway station, emerging
in some kind of alley.""")
            DIPL = DIPL + 1
            input()
            seedyhotel(obj)
        elif "escape" in choice and not failtry:
            print("""You squirm away just as the doors are about to close,
onto the platform, alone. Ahem, not at all alone, but without her.
You fish in your pocket and still have the Beijing subway map...
Sanlitun. Sanlitun. You find the line and push into the crowd.""")
            print("""Three cars pass before you're able to board, but finally
you do. An hour later, you're swept off, swept up the stairs to the street.""")
            DIPL = DIPL + 4
            input()
            hotel(obj)
        else:
            print("Nothing works, nothing would work, she's alert, eyes jumpy.")
            DIPL = DIPL + 2
            failtry = True
            input()

def car(obj):
    global DIPL
    check(DIPL)
    input()
    print(f"""The driver throws your {obj} into the trunk with a crash.
You hear it banging around as he drives. Races? You feel a little sick.""")
    INV.append(f"{obj}")
    speak = input("> ")

    if "please" in speak:
        print("The bastard speeds up, and you puke on yourself for the rest of the ride.")
        print(f"""He screeches up to the front door of your hotel and you find yourself
on the curb with your {obj} on the ground, not feeling so hot.""")
        DIPL = DIPL - 5
        input()
        hotel(obj)

    else:
        print(f"""He ignores you, screeching up to your hotel.
You find yourself left on the curb with your {obj} on the ground,
not feeling so hot.""")
        DIPL = DIPL - 1
        input()
        hotel(obj)

def alone(obj):
    global DIPL
    check(DIPL)
    input()
    print("""As you walk away from the crush, the voices seem to muffle into the smog.
There is still a steady flow of passengers passing in all directions around you,
but it somehow feels lonlier. Quieter.
Just as you start to notice the concrete tiles of the walkway are loose,
some cracked, some missing, you hear a voice: "Mister!""")
    print("""You're standing at the sliding door of some forgotten corner of the airport,
the sound of oversized heels clacking toward you. "Mister!"
Do you turn around or go through the door?""")

    react = input("> ")

    if "turn" in react:
        print("""You turn to see a young woman running toward you. She's wearing a
black bra, white shirt with the hem high above her belly button, with bleached
orange hair and cutoff jeans shorts so tiny the pockets flap outside of them.""")
        input()
        print(""""Mister," as she grabs your arm, her fingers surprisingly strong,
"come with me.\"""")
        DIPL = DIPL + 8
        input()
        subway2("fake passport")
    elif "door" in react:
        print("""You slip inside the door, a blast of dank, air conditioned air
hitting your face. You realize it's the entrance to the subway. You fish in your
pocket and still have the Beijing subway map... Sanlitun. Sanlitun. You find the
line, drop a coin in the meter, and push into the crowd.""")
        DIPL = DIPL + 3
        input()
        subway(obj)
    else:
        print("""Her voice suddenly stops, but when you turn back around,
you can't find the door. Just then a taxi pulls up
and the driver waves at you, so you get inside.""")
        DIPL= DIPL + 2
        input()
        car(obj)

def start():
    global DIPL
    print("""You see a brown haze slide past the window of the plane
as the landing gear grinds lower. Slowly, the patches of remaining hutong,
willow trees, and crowded bicycles that are signatures of the Beijing streets
grow visible below through the grime.""")
    print("""As the plane lands, and while it taxis, the people around you unbuckle
their seatbelts and begin to stand, pulling luggage
from the overhead compartments.""")
    print("""After hours of being jostled and pushed while waiting in line at
customs, and after being shouted at by an immigration officer who refuses to
recognize your diplomatic passport, you are let into the country.
Standing outside the gate is a Chinese man playing on his mobile phone
and holding a placard with your name. Nobody told you he would be
picking you up; what do you do?""")
    outside = False

    choose = input("> ")

    while True:
        if "ask" in choose and not outside:
            print("""Without speaking or looking at you, he turns around and begins to walk.
You grab your luggage, pushing through the constant crowd to hurry after him.""")
            DIPL = DIPL + 1
            outside = True
            input()
            car("luggage")
        elif "out" in choose or outside:
            print("""Outside the airport, a swarm of taxi drivers surrounds you.
In the push and pull, your luggage is twisted from your grasp. Even your
passport, which you were still holding in your hand,
is almost taken, but you manage to hold onto it.""")
            DIPL = DIPL - 5
            outside = True
            input()
            alone("damaged passport")
        else:
            print("""Jet lag is sinking in. You wander through endless halls at the airport,
bumped and pushed, until you suddenly find yourself outside.""")
            outside = True
            input()

start()

Hi and welcome. Many of us have approach this at ex36 with text-heavy games. I wouldn’t sweat it too much here as you rewrite the game a few more times during the book.

I’d suggest making note when you come across a python feature that you’d like to learn and try to implement it into the game. Even if you don’t get them fully, trying to implement them will help your understanding.

So you could explore comprehensions, especially list comprehension. Generators can be useful for game battles. Using sets and associated methods for comparison (like checking itinerary contents or something). How about extracted the text parts to another module and importing them in to keep the code clean? Or even write tests (but that’s coming anyway!)

Lots of options really.

1 Like

Generators could work but really a simple while loop that keeps going until either the player or the boss dies would be easiest. Just make it that once they enter that room they have to fight and can’t leave and then that’s it.

2 Likes

Thanks! I started with ex37 (which has been massively challenging) and have been trying to use a class and a while loop to design the fight scene for this one. I’m stuck on a problem though where the stats for all kicks are decided when the loop first runs, but I want each iteration of a kick to have a different stat.

import random
HP = 100
enemy_HP = 100

class Move():
    damage = random.randint(-3, 1)
    damage_received = random.randint(-4, 1)
    heal = random.randint(0, 2)

punch = Move()
kick = Move()
bite = Move()

kick.damage = random.randint(-4, 0)
kick.damage_received = random.randint(-5, -1)
bite.damage = random.randint(-5, -3)
bite.damage_received = random.randint(-5, -3)
bite.heal = 0

def start():
    global HP
    global enemy_HP
    while HP > 0:
        choose = input("Choose a move: ")
        if "p" in choose:
            HP = HP + punch.damage_received + punch.heal
            enemy_HP = enemy_HP + punch.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        elif "k" in choose:
            HP = HP + kick.damage_received + kick.heal
            enemy_HP = enemy_HP + kick.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        elif "b" in choose:
            HP = HP + bite.damage_received + bite.heal
            enemy_HP = enemy_HP + bite.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        else:
            print("Double dodge!")
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")

start()

I’m aware I also need to find a way for you to win, because as written you’ll just keep fighting until you die, with the opponent running into negative points if you’re beating him.

Hmm. The technical problem is that you define the stats as class variables of your Move class. If you want them to be different, you need to make instance variables.

The difference is that class variables are bound to the class, thus they’re the same for all instances of the class. Instance variables can have individual values in each instance.

class Move(object):
    # Class variables would go here, inside the class block
    # outside method definitions.
    def __init__(self):
        # Instance variables are defined inside methods.
        # The __init__ method is called implicitly when you create
        # an instance of the class, so now each instance gets new
        # random stats.
        self.damage = random.randint(-3, 1)
        self.damage_received = random.randint(-4, 1)
        self.heal = random.randint(0, 2)

If you do it this way, you’ll need to create a new Move instance in each iteration of the loop. For example:

while HP > 0:
    bite = Move()    # Move.__init__ is called implicitly.
    HP += bite.damage_received + bite.heal
    enemy_HP += bite.damage

If you want bites and kicks and stabs and punches and to have different ranges for their stats, you can create a different class for each.

2 Likes

Thanks! I was wondering how to integrate functions in to a class definition, so this gives me some food for thought. I set it up as below:

import random
HP = 100
enemy_HP = 100

class Move(object):
    def __init__(self):
        damage = random.randint(-3, 1)
        damage_received = random.randint(-4, 1)
        heal = random.randint(0, 2)

def start():
    global HP
    global enemy_HP
    while HP > 0:
        punch = Move()
        kick = Move()
        bite = Move()
        kick.damage = random.randint(-4, 0)
        kick.damage_received = random.randint(-5, -1)
        bite.damage = random.randint(-5, -3)
        bite.damage_received = random.randint(-5, -3)
        bite.heal = 0
        choose = input("Choose a move: ")
        if "p" in choose:
            HP += punch.damage_received + punch.heal
            enemy_HP += punch.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        elif "k" in choose:
            HP += kick.damage_received + kick.heal
            enemy_HP += kick.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        elif "b" in choose:
            HP += bite.damage_received + bite.heal
            enemy_HP += bite.damage
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")
        else:
            print("Double dodge!")
            print(f"HP: {HP}\nEnemy HP: {enemy_HP}")

start()

However, when I run it, it only recognizes the moves I defined within the loop (i.e. kick.damage but not kick.heal), crashing with an AttributeError: ‘Move’ object has no attribute ‘heal’. Why isn’t it just going up to Move.init and grabbing the heal stat from there like it did before I added the function to the class definition?

I’m also a little confused as to the tip on creating a different class for each move. If I can’t get the loop to grab stats directly from the Move class, I’m not sure how I would make it work with three classes (kick, bite, punch). I’m also a little confused about the purpose of classes in that case, too, as I thought the benefit was to make a sort of template for an object that I can modify as I go to make new objects… i.e. why would I need three templates?

Oh! I’m sorry, I made a mistake in my example. I’ve edited it now, you need to assign to self.damage etc.

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