def tick(self, events):
        """Execute one frame of the interpreter.

        Don't call more than 40 times per second.

        """
        self.add_new_threads()

        if self.drag_sprite:
            (mx, my) = self.screen.get_mouse_pos()
            (ox, oy) = self.drag_offset
            new_position = (mx + ox, my + oy)
            if self.drag_sprite.position != new_position:
                self.has_dragged = True
                self.drag_sprite.position = new_position

        for event in events:
            if event.kind == "key_pressed":
                assert event.value in kurt.Insert(None, "key").options()
                self.trigger_hats("whenKeyPressed", event.value)

            elif event.kind == "mouse_down":
                mouse_pos = self.screen.get_mouse_pos()
                for sprite in reversed(self.project.sprites):
                    rect = bounds(sprite)
                    if rect.collide_point(mouse_pos):
                        if self.screen.touching_mouse(sprite):
                            scriptable = sprite
                            break
                else:
                    scriptable = self.project.stage

                if scriptable.is_draggable:
                    (mx, my) = self.screen.get_mouse_pos()
                    (x, y) = scriptable.position
                    self.drag_offset = (x - mx, y - my)
                    self.drag_sprite = scriptable
                    self.has_dragged = False
                    go_to_front(scriptable)
                else:
                    self.trigger_scriptable_hats(scriptable, "whenClicked")

            elif event.kind == "mouse_up":
                if self.drag_sprite:
                    if not self.has_dragged:
                        self.trigger_scriptable_hats(self.drag_sprite,
                                                     "whenClicked")
                    self.drag_sprite = None

        remove_threads = []
        while 1:
            for (script, thread) in self.threads.items():
                modified = False
                for event in thread.tick():
                    if event.kind == "stop":
                        if event.value == "all":
                            self.stop()
                            return
                        elif event.value == "other scripts in sprite":
                            for (script, other) in self.threads.items():
                                if other.scriptable == thread.scriptable:
                                    other.finish()
                                    del self.threads[script]
                            modified = True
                            break
                        else:
                            thread.finish()
                            del self.threads[script]
                            modified = True
                            break
                    else: # Pass to Screen
                        yield event
                if modified:
                    break
            else:
                break

        self.add_new_threads()
Execute one frame of the interpreter.

        Don't call more than 40 times per second.