4

After I got the hang of my previous programme (the turtle that walked randomly and bounced off the walls until it hit them 4 times), I tried doing the following exercise in the guide, which asks for two turtles with random starting locations that walk around the screen and bounce off the walls until they bump into each other – no counter variable to decide when they should stop. I managed to write the entire thing except for the part where they collide and stop: I figured a boolean function that returns True if the turtles' X and Y coordinates are the same and False if they aren't would do the job, but instead they keep walking and the only way to terminate the programme is to force the interpreter to quit. What am I doing wrong?

import turtle
import random

def setStart(t):
    tx = random.randrange(-300,300,100)
    ty = random.randrange(-300,300,100)

    t.penup()
    t.goto(tx,ty)
    t.pendown()

def throwCoin(t):
    coin = random.randrange(0,2)

    if coin == 0:
        t.left(90)
    else:
        t.right(90)

def isInScreen(w,t):
    leftBound = w.window_width() / -2
    rightBound = w.window_width() / 2
    bottomBound = w.window_height() / -2
    topBound = w.window_height() / 2

    turtlex = t.xcor()
    turtley = t.ycor()

    stillIn = True

    if turtlex < leftBound or turtlex > rightBound or turtley < bottomBound or turtley > topBound:
        stillIn = False

    return stillIn

def collide(t,u):
    if t.xcor() == u.xcor() and t.ycor() == u.ycor():
        return True
    return False

def randomWalk(t,w):
        if not isInScreen(w,t):
            t.left(180)
        else:
            throwCoin(t)
        t.forward(100)

def doubleRandom(t,u,w):
    while not collide(t,u):
        randomWalk(t,w)
                if collide(t,u):
                   break
        randomWalk(u,w)

wn = turtle.Screen()
wn.bgcolor('lightcyan')

steklovata = turtle.Turtle()
steklovata.color('darkslategray')
steklovata.shape('turtle')
setStart(steklovata)

catshower = turtle.Turtle()
catshower.color('orangered')
catshower.shape('turtle')
setStart(catshower)

doubleRandom(steklovata,catshower,wn)

wn.exitonclick()

EDIT: in order to test whether the bug was in the collide(t,u) function or in the while loop that calls it, I wrote another function that sends both turtles to the same spot and prints out some text (if anyone's wondering, it's an inside joke, like every flipping name I come up with) if collide(t,u) returns True. When I ran it the text DID print out, which tells me that the collision detection is working properly... but the loop somehow isn't telling Python that the turtles should stop when they collide. This is the function:

def raul(t,u,w):
    t.goto(1,1)
    u.goto(1,1)
    if collide(t,u):
        t.write('RAUL SUNTASIG')

Does this give you guys any ideas as to why it's not working?

reggaelizard
  • 811
  • 2
  • 12
  • 31
  • I haven't even looked at the code yet, but could the problem be that they stop intersecting before the collision check happens? For example, a turtle at `(0, 0)` goes to `(1, 0)`, and the other turtle goes from `(1, 0)`, to `(0, 0)`, and then the collision logic thinks they haven't hit each other? – user2357112 Aug 05 '13 at 21:15
  • I think by Python's logic one is going from, say, `0,1`to `0,0` and instantly afterwards the other one goes from `1,0` to `0,0`, so I reckon the coordinates should be the same, but the first turtle walks again and then so does the other one instead of both stopping at the spot. – reggaelizard Aug 05 '13 at 21:19
  • That only happens if they start an even number of steps away from each other. If they start at `(0, 0)` and `(0, 1)`, the collision detector will never notice when they collide. – user2357112 Aug 05 '13 at 21:24
  • Does your code stop some of the time? If so, about how often? Half the time? Less? – user2357112 Aug 05 '13 at 21:27
  • @user2357112 it never stops, even when the turtles meet they keep walking. – reggaelizard Aug 06 '13 at 01:27
  • No, I mean if you stop it and retry repeatedly, does it work sometimes? – user2357112 Aug 06 '13 at 01:28
  • No, I've tried about 20 times and it never worked. – reggaelizard Aug 06 '13 at 01:46
  • 1
    Found the problem. Check out my edits. – Ethan Furman Aug 06 '13 at 04:11
  • @EthanFurman oh man I can't thank you enough for this. It actually worked! – reggaelizard Aug 06 '13 at 04:37

3 Answers3

1

Edit: Completely changed answer.

I added print statements to the collide routine and got this:

-300.0 -200.0 -100.0 -100.0
-300.0 -100.0 -100.0 -100.0
-300.0 -100.0 -200.0 -100.0
-300.0 -100.0 -200.0 -100.0
-300.0 1.13686837722e-13 -200.0 -100.0
-300.0 1.13686837722e-13 -200.0 1.27897692437e-13
-300.0 1.13686837722e-13 -200.0 1.27897692437e-13
-200.0 4.02080297728e-14 -200.0 1.27897692437e-13
-200.0 4.02080297728e-14 -200.0 100.0
-200.0 4.02080297728e-14 -200.0 100.0

Here's how you fix it:

def collide(t,u):
    if abs(t.xcor() - u.xcor()) < 1 and abs(t.ycor() - u.ycor()) < 1:
        return True
    return False

Oh, and you should do a collide() check after each randomWalk(), not just the first one.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
0

Your code only checks collision after both turtles move. About half the time, the turtles will start an odd number of steps away from each other, in which case they'll always be an odd number of steps away from each other when the collision detection runs. Even if one of them moves onto the other's spot, the other will move away before you check for collision. To fix this, run an additional collision check between moves:

while not collide(t, u):
    randomWalk(t, w)
    if collide(t, u):
        break
    randomWalk(u, w)

There's another thing to consider; the turtles always make right turns, or 180s when they hit a wall. This introduces parity concerns similar to the above, which could prevent or delay a collision if the turtles can't make the right turn sequence or have to wait until they make just the right wall collisions to point them in the right directions. You could fix this by making the turtles randomly choose from all 4 directions to walk in:

def throwCoin(t):
    # 4-sided Ruritanian nickel
    t.left(90*random.randrange(4))
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • I just tried this once and it worked, so I tried 2 more times to see if it worked every time but it didn't. I think the difference was that the first time neither of the turtles had hit a wall, but the second two they did, but I don't see how that can affect the collision detection and I'm surprised it's not working since your code seems to make a lot of sense. – reggaelizard Aug 06 '13 at 02:03
  • @reggaelizard: Posted another problem. I'm not sure whether it actually prevents collisions, but fixing it will probably make collisions happen faster, which may be important if you're not waiting long enough to see the results. – user2357112 Aug 06 '13 at 02:30
  • Still not working, collisions have happened several times but they're not stopping. (Nice Ruritanian nickel though, goes well with my turtle named after a Russian boy band). – reggaelizard Aug 06 '13 at 02:51
0

Use larger turtles.

If you're currently only calling it a collision if the x and y coordinates of the two turtles match exactly, that is going to be a very hard condition to meet.

If you imagine that your turtles to have a radius of 5 points, then any time the distance between the two turtles' center points is less than 10, they will have collided.

jwygralak67
  • 924
  • 7
  • 13
  • They only move 100 steps at a time and their starting coordinates are always multiples of 100, which makes the odds that they'll meet a lot bigger (and in fact I've seen them meet several times). I might try what happens if I change the condition to `(abs(t.xcor()-u.xcor) < 10` and so on though. – reggaelizard Aug 06 '13 at 01:25
  • I changed it so that they collide every time the distance is less than 10 and they took 100 steps and just stopped, even though they were very far apart from each other. Every time I ran it they stopped after taking one turn each. Do you have an idea why this could be happening? – reggaelizard Aug 06 '13 at 01:54
  • You also have to check the y-coordinate. You should really do something like sqrt(x*x + y*y) where x is the diff between x-coords and y - the diff between the y coords of the two turtles. – jwygralak67 Aug 06 '13 at 17:17