0

I'm programming a game where enemy turtles (called badturt in the program) chase the user's turtle. The user can make its turtle attack the enemy turtles by sending an attack (another turtle).

In lvl 2, there are two enemy turtles chasing the user's turtle. To make one enemy turtle stop moving (after it is attacked/hit), I tried to redefine the function that makes the enemy turtle move, which was done inside another function. (I redefined it to None)

attack = turtle.Turtle()
#...attributes

def turtleattack():
    global lvl
    global q
    global w
    global e
    #... positioning attack
    for i in range(75):
        attack.forward(10)
        if lvl == 1:
            Chase(badturt)
        if lvl == 2:
            Chase(badturt)
            Chase(badturt2)
        if lvl == 3:
            Chase(badturt)
            Chase(badturt2)
            Chase(badturt3)
        IfAttackHit()
bg.onkeypress(turtleattack, 'z')
bg.listen()


def Chase(bt): #makes bad turt (bt) chase turt
    bt.setheading(bt.towards(turt))
    bt.forward(11)

def StopChase(bt):
    global lvl
    global win
    #global Chase <---------------- program stops running if I write it in
    if lvl == 1:
        #...
    if lvl == 2:
        def Chase(bt):
            None
        if q == 2 and w == 2:
            lvl = 3
            writeinfo()
    if lvl == 3:
        def Chase(bt):
            None
        if q == 3 and w == 3 and e == 3:
            #... (winning the game)

def ChaseAgain(bt): #makes badturt chase again when it moves onto next lvl
    def Chase(bt):
        bt.setheading(badturt.towards(turt))
        bt.forward(11)
    Chase(bt)


def IfAttackHit():
    global win
    global lvl
    global q
    global w
    global e
    if lvl == 1:
        if badturt.distance(attack) < 20:
            badturt.hideturtle()
            attack.hideturtle()
            badturt.goto(300,350)
            q = 1
            StopChase(badturt) #<---- doesn't work
    if lvl == 2:
        if badturt.distance(attack) < 20:
            badturt.hideturtle()
            attack.hideturtle()
            badturt.goto(300,350)
            q = 2
            StopChase(badturt)
        if badturt2.distance(attack) < 20:
            badturt2.hideturtle()
            badturt2.goto(-300,350)
            attack.hideturtle()
            w = 2
            StopChase(badturt2)
    if lvl == 3:
        #same format as lvl 2 but with addition of badturt3


while True:
    if lvl == 1:
         while True:
            CheckDamage()
            if turthealth == 0:
                LOSE()
                break
            IfAttackHit()
            Chase(badturt)
            if q == 1:
                break
    break
    if lvl == 2:
        ChaseAgain(badturt) #make it move again
        ChaseAgain(badturt2)
        badturt.goto(300,350)
        badturt.showturtle()
        badturt2.showturtle()
        while True:
            CheckDamage()
            if turthealth == 0:
                LOSE()
                break
            IfAttackHit()
            Chase(badturt)
            Chase(badturt2)
    break
    if lvl == 3:
        #same format as lvl 2 but with addition of badturt3
        break

This didn't work. Was it because it was nested inside another function? Was StopChase() never called? Did the function get redefined again so that the enemy turtle started moving again?

Also, my teacher told me that I had to write 'global Chase' to redefine it within another function, but when I do, the program stops running at that point - when I move my cursor over the turtle screen, it just shows the loading cursor, and nothing happens on the screen/it freezes. (Was it wrong to do that, or is it an issue with the python program on my laptop?)

I also tried redefining Chase() so that badturt would only move forward 0 (essentially making it do nothing), but that didn't work either.

Please let me know what I'm doing wrong, or if there's another way to make badturt stop moving.

2 Answers 2

2

When you redefine a non-class method the redefinition is permanent meaning it applies to everything. You probably don't want that.

What speaks against writing a condition inside of your Chase method?


There are various bad coding practices in your code:

  • You should generally refrain from using global. You should create classes and instances of classes which have attributes and pass those instances around.
  • Methods aren't capitalized. Classes are capitalized.
  • You have some unreachable code due to break
  • Use pass instead of None when nothing is supposed to happen
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your advice. Just wondering, why is it bad practice to use global? I’m a beginner (if you didn’t already know from my poor coding), so I don’t really know that much about how to format my code.
It leads to some very hacky and confusing code. You need a bit more structure in your code and that can be achieved with classes. All the relevant attributes a class should have is inside the instance. It also scales better because once you define a global variable that variable name is gone. For instance you have a global variable called level. Later you want to track the levels of other objects. With classes you could do turtle1.level and turtle2.level. You can put turtle1 and turtle2 into a list of turtles etc.
@whattheheck--there are many discussions such as Global Variables are Evil that explain why they should be avoided. They do have a role but generally is a design smell when seen in code.
0

Tin Nguyen is absolutely right and you should definitely follow his advices. I'd just like to elaborate on your first question. Even if it could be bad, redefining your function using global should work. Here is what I tried as a minimal example:

def f():
    print("f")

def g():
    global f
    def f():
        print("f_prime")

f()
g()
f()

When called I get:

f
f_prime

The explanation why your program stops must be elsewhere but you do not provide the error you faced, if any.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.