Turtle module for langtons ant in python giving me raise Terminator - turtle.Terminator Error

Viewed 61
import turtle


def update_maps(graph, turtle, color):
    graph[turtle_pos(turtle)] = color
    return None


def turtle_pos(turtle):
    return (round(turtle.xcor()), round(turtle.ycor()))


def langton_move(turtle, pos, maps, step):
    if pos not in maps or maps[pos] == "white":
        turtle.fillcolor("black")
        turtle.stamp()
        update_maps(maps, turtle, "black")
        turtle.right(90)
        turtle.forward(step)
        pos = turtle_pos(turtle)
    elif maps[pos] == "black":
        turtle.fillcolor("white")
        update_maps(maps, turtle, "white")
        turtle.stamp()
        turtle.left(90)
        turtle.forward(step)
        pos = turtle_pos(turtle)
    return pos


def move(movements,trace):
    # Screen
    BACKGROUND_COLOR = "white"
    WIDTH = 2000
    HEIGHT = 2000
    # Ant
    SHAPE = "square"
    SHAPE_SIZE = 0.5
    SPEED = -1
    STEP = 11

    # Data structure ex. {(x, y): "black", ..., (x_n, y_n): "white"}
    maps = {}

    # Initialize Window
    window = turtle.Screen()
    window.bgcolor(BACKGROUND_COLOR)
    window.screensize(WIDTH, HEIGHT)
    window.tracer(trace)
    # Initialize Ant
    ant = turtle.Turtle()
    ant.shape(SHAPE)
    ant.shapesize(SHAPE_SIZE)
    ant.penup()
    ant.speed(SPEED)
    ant.right(180)
    pos = turtle_pos(ant)

    moves = 0
    while moves<movements:
        pos = langton_move(ant, pos, maps, STEP)
        moves += 1
    window.exitonclick()

while True:
    option = int(input("hey"))
    if option == 1:
        move(11000, False)
    if option == 2:
        move(100, True)

the code above works and it will display langtons ant and i can keep pressing option 1 forever and it will work, it will also work if option 2 (trace is on) is first and then i go on to press option 1 and display langtons ant, however after pressing option 1 even only once, if i try to press option 2 it will raise a turtle.Terminator Error, which means that option 2 only works if its pressed first, and no times after that, please help me as i am very stuck.

2 Answers

The problem is that your program is structured incorrectly. You make use of turtle to do your drawing, but ignore the programing paradigm of turtle. There should be no while True: in an event-driven world. You should be typing the numbers at the screen (with no return) instead of the console. You shouldn't be creating a new (global) ant for each run but rather reusing the old one. You don't need to completely reinitialize everything about the window on every run. The exitonclick() should only be called once, not in a loop.

Below is my rework of your code that I think behaves the way you intended. I uses screen key events so just type a number and it will start drawing -- don't go back to the console. Just before drawing, it clears the previous drawing and resets the ant and the trace mode:

from turtle import Screen, Turtle

# Screen
WIDTH = 2000
HEIGHT = 2000
BACKGROUND_COLOR = 'white'

# Ant
SHAPE = 'square'
SHAPE_SIZE = 0.5
SPEED = 'fastest'
STEP = 11

def update_maps(graph, turtle, color):
    graph[turtle_pos(turtle)] = color

def turtle_pos(turtle):
    x, y = turtle.position()

    return round(x), round(y)

def langton_move(turtle, pos, maps, step):
    if pos not in maps or maps[pos] == 'white':
        turtle.fillcolor('black')
        turtle.stamp()
        update_maps(maps, turtle, 'black')
        turtle.right(90)
    elif maps[pos] == 'black':
        turtle.fillcolor('white')
        turtle.stamp()
        update_maps(maps, turtle, 'white')
        turtle.left(90)

    turtle.forward(step)

    return turtle_pos(turtle)

def move(movements, trace):
    # Data structure ex. {(x, y): 'black', ..., (x_n, y_n): 'white'}
    maps = {}

    screen.tracer(trace)

    ant.home()
    ant.clear()
    ant.setheading(180)

    screen.update()

    position = turtle_pos(ant)

    for _ in range(movements):
        position = langton_move(ant, position, maps, STEP)

def long_untraced():
    screen.onkey(None, '1')  # disable handlers inside handler
    screen.onkey(None, '2')

    move(11000, False)

    screen.onkey(long_untraced, '1')  # reenable handlers
    screen.onkey(short_traced, '2')

def short_traced():
    screen.onkey(None, '2')  # disable handlers inside handler
    screen.onkey(None, '1')

    move(100, True)

    screen.onkey(short_traced, '2')  # reenable handlers
    screen.onkey(long_untraced, '1')

# Initialize Window
screen = Screen()
screen.screensize(WIDTH, HEIGHT)
screen.bgcolor(BACKGROUND_COLOR)

# Initialize Ant
ant = Turtle()
ant.shape(SHAPE)
ant.shapesize(SHAPE_SIZE)
ant.penup()
ant.speed(SPEED)

screen.onkey(long_untraced, '1')
screen.onkey(short_traced, '2')
screen.listen()
screen.exitonclick()

Adding this single line before the

#InitializeAnt comment statement will help you to get this code working as intended.

...
turtle.TurtleScreen._RUNNING=True
# Initialize Ant
...
Related