Question: Whenever I try and run my program, it draws the two turtles and then the window stops responding. What I was expecting is that, until one of the pieces touches the other one based on me dragging it close to the other one, I will be able to drag both of them by themselves. What's happening though is that whenever I run the program, after drawing both of the turtles, the window stops responding. I don't get any errors, it just closes after freezing until I click the close button. I've looked at other people's post where they had this problem but they haven't had screen.mainloop() at the end and I do. import turtle captured_pieces = [] blue = turtle.Turtle() black = turtle.Turtle() screen = turtle.Screen() blue.penup() black.penup() blue.shape('square') black.shape('triangle') blue.setpos(100,100) black.setpos(-100,-100) blue.color('blue') black.color('black') def bmove(): black.ondrag(black.goto) if black.distance(blue) < 30: captured_pieces.append("BlC") print(captured_pieces) check() def blmove(): blue.ondrag(blue.goto) if blue.distance(black) < 30: captured_pieces.append("BC") print(captured_pieces) check() def check(): if "BlC" in captured_pieces: print("blue captured") def check(): if "BC" in captured_pieces: print("black captured") while "BlC" not in captured_pieces and "BC" not in captured_pieces: bmove() blmove() screen.mainloop() 

Answer: The while loop does two things over and over: add drag handlers, and check distance. The loop doesn't call any turtle methods that cause turtle's rendering/event loop to run (for example, .forward() or .goto()), so the distance checks can't be true to break the loop. We want to get to mainloop() to enable user interaction, but we can't get there unless user interaction is allowed--we're stuck. Avoid the loop (you generally don't want to use while in a real-time turtle program) and check for collisions inside the drag handlers rather than in the loop, then let mainloop() run the turtle rendering loop. This reveals a new problem: the internal loop's "gliding" speed causes dragging to be very glitchy. You can use tracer(0) to disable the internal loop and turtle.update() to manually trigger repaints when you need them, eliminating any gliding behavior and giving you full control of rerenders. Here's a simple example: import turtle turtle.tracer(0) blue = turtle.Turtle() black = turtle.Turtle() screen = turtle.Screen() blue.penup() black.penup() blue.shape("square") black.shape("triangle") blue.setpos(100, 100) black.setpos(-100, -100) blue.color("blue") black.color("black") def handle_drag(piece, other, x, y): piece.goto(x, y) turtle.update() if piece.distance(other) < 30: print("capture:", piece.color()[0], other.color()[0]) black.ondrag(lambda x, y: handle_drag(black, blue, x, y)) blue.ondrag(lambda x, y: handle_drag(blue, black, x, y)) turtle.update() screen.mainloop()  Before long, you'll likely need custom classes (like a Piece class, which might be subclassed by various types of pieces with different characteristics) and data structures. The approach above with separate variables isn't scalable. But I'll leave it as is for now in the interest of keeping it scoped to your immediate problem.