鱼C论坛

 找回密码
 立即注册
查看: 733|回复: 9

turtle

[复制链接]
发表于 2021-2-19 11:00:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 xsywa 于 2021-2-19 11:09 编辑

都是turtle是内置库,可我的怎么用不了
尤其按照网上的教程再重新安装,点不开turtle.py
微信截图_20210219110652.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-19 11:05:28 | 显示全部楼层
打错了
import

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-19 11:06:33 | 显示全部楼层

额,这个没注意,改了后也是一样的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-19 13:40:47 | 显示全部楼层
你的python是什么版本的,你下载的该包是否在模块路径中,麻烦详细描述一下问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-19 14:03:39 | 显示全部楼层
本帖最后由 考不好不改名 于 2021-2-19 14:05 编辑

建议重装Python
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-19 14:08:29 | 显示全部楼层
你找到你Python安装的目录(默认是C:\Users\33260\AppData\Local\Programs\Python);在目录下打开Lib,看看有没有一个叫turtle.py的文件;如果没有,新建一个同名文件,并打开输入以下代码:
  1. _ver = "turtle 1.1b- - for Python 3.1   -  4. 5. 2009"

  2. import tkinter as TK
  3. import types
  4. import math
  5. import time
  6. import inspect
  7. import sys

  8. from os.path import isfile, split, join
  9. from copy import deepcopy
  10. from tkinter import simpledialog

  11. _tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
  12.                'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
  13. _tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
  14.         'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
  15.         'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
  16.         'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
  17.         'register_shape', 'resetscreen', 'screensize', 'setup',
  18.         'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
  19.         'window_height', 'window_width']
  20. _tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
  21.         'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
  22.         'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
  23.         'fillcolor', 'filling', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
  24.         'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
  25.         'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
  26.         'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
  27.         'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
  28.         'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
  29.         'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
  30.         'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
  31.         'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
  32.         'write', 'xcor', 'ycor']
  33. _tg_utilities = ['write_docstringdict', 'done']

  34. __all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
  35.            _tg_utilities + ['Terminator']) # + _math_functions)

  36. _alias_list = ['addshape', 'backward', 'bk', 'fd', 'ht', 'lt', 'pd', 'pos',
  37.                'pu', 'rt', 'seth', 'setpos', 'setposition', 'st',
  38.                'turtlesize', 'up', 'width']

  39. _CFG = {"width" : 0.5,               # Screen
  40.         "height" : 0.75,
  41.         "canvwidth" : 400,
  42.         "canvheight": 300,
  43.         "leftright": None,
  44.         "topbottom": None,
  45.         "mode": "standard",          # TurtleScreen
  46.         "colormode": 1.0,
  47.         "delay": 10,
  48.         "undobuffersize": 1000,      # RawTurtle
  49.         "shape": "classic",
  50.         "pencolor" : "black",
  51.         "fillcolor" : "black",
  52.         "resizemode" : "noresize",
  53.         "visible" : True,
  54.         "language": "english",        # docstrings
  55.         "exampleturtle": "turtle",
  56.         "examplescreen": "screen",
  57.         "title": "Python Turtle Graphics",
  58.         "using_IDLE": False
  59.        }

  60. def config_dict(filename):
  61.     with open(filename, "r") as f:
  62.         cfglines = f.readlines()
  63.     cfgdict = {}
  64.     for line in cfglines:
  65.         line = line.strip()
  66.         if not line or line.startswith("#"):
  67.             continue
  68.         try:
  69.             key, value = line.split("=")
  70.         except ValueError:
  71.             print("Bad line in config-file %s:\n%s" % (filename,line))
  72.             continue
  73.         key = key.strip()
  74.         value = value.strip()
  75.         if value in ["True", "False", "None", "''", '""']:
  76.             value = eval(value)
  77.         else:
  78.             try:
  79.                 if "." in value:
  80.                     value = float(value)
  81.                 else:
  82.                     value = int(value)
  83.             except ValueError:
  84.                 pass # value need not be converted
  85.         cfgdict[key] = value
  86.     return cfgdict

  87. def readconfig(cfgdict):
  88.     default_cfg = "turtle.cfg"
  89.     cfgdict1 = {}
  90.     cfgdict2 = {}
  91.     if isfile(default_cfg):
  92.         cfgdict1 = config_dict(default_cfg)
  93.     if "importconfig" in cfgdict1:
  94.         default_cfg = "turtle_%s.cfg" % cfgdict1["importconfig"]
  95.     try:
  96.         head, tail = split(__file__)
  97.         cfg_file2 = join(head, default_cfg)
  98.     except Exception:
  99.         cfg_file2 = ""
  100.     if isfile(cfg_file2):
  101.         cfgdict2 = config_dict(cfg_file2)
  102.     _CFG.update(cfgdict2)
  103.     _CFG.update(cfgdict1)

  104. try:
  105.     readconfig(_CFG)
  106. except Exception:
  107.     print ("No configfile read, reason unknown")


  108. class Vec2D(tuple):
  109.     def __new__(cls, x, y):
  110.         return tuple.__new__(cls, (x, y))
  111.     def __add__(self, other):
  112.         return Vec2D(self[0]+other[0], self[1]+other[1])
  113.     def __mul__(self, other):
  114.         if isinstance(other, Vec2D):
  115.             return self[0]*other[0]+self[1]*other[1]
  116.         return Vec2D(self[0]*other, self[1]*other)
  117.     def __rmul__(self, other):
  118.         if isinstance(other, int) or isinstance(other, float):
  119.             return Vec2D(self[0]*other, self[1]*other)
  120.         return NotImplemented
  121.     def __sub__(self, other):
  122.         return Vec2D(self[0]-other[0], self[1]-other[1])
  123.     def __neg__(self):
  124.         return Vec2D(-self[0], -self[1])
  125.     def __abs__(self):
  126.         return (self[0]**2 + self[1]**2)**0.5
  127.     def rotate(self, angle):
  128.         """rotate self counterclockwise by angle
  129.         """
  130.         perp = Vec2D(-self[1], self[0])
  131.         angle = angle * math.pi / 180.0
  132.         c, s = math.cos(angle), math.sin(angle)
  133.         return Vec2D(self[0]*c+perp[0]*s, self[1]*c+perp[1]*s)
  134.     def __getnewargs__(self):
  135.         return (self[0], self[1])
  136.     def __repr__(self):
  137.         return "(%.2f,%.2f)" % self

  138. def __methodDict(cls, _dict):
  139.     """helper function for Scrolled Canvas"""
  140.     baseList = list(cls.__bases__)
  141.     baseList.reverse()
  142.     for _super in baseList:
  143.         __methodDict(_super, _dict)
  144.     for key, value in cls.__dict__.items():
  145.         if type(value) == types.FunctionType:
  146.             _dict[key] = value

  147. def __methods(cls):
  148.     """helper function for Scrolled Canvas"""
  149.     _dict = {}
  150.     __methodDict(cls, _dict)
  151.     return _dict.keys()

  152. __stringBody = (
  153.     'def %(method)s(self, *args, **kw): return ' +
  154.     'self.%(attribute)s.%(method)s(*args, **kw)')

  155. def __forwardmethods(fromClass, toClass, toPart, exclude = ()):
  156.     ### MANY CHANGES ###
  157.     _dict_1 = {}
  158.     __methodDict(toClass, _dict_1)
  159.     _dict = {}
  160.     mfc = __methods(fromClass)
  161.     for ex in _dict_1.keys():
  162.         if ex[:1] == '_' or ex[-1:] == '_' or ex in exclude or ex in mfc:
  163.             pass
  164.         else:
  165.             _dict[ex] = _dict_1[ex]

  166.     for method, func in _dict.items():
  167.         d = {'method': method, 'func': func}
  168.         if isinstance(toPart, str):
  169.             execString = \
  170.                 __stringBody % {'method' : method, 'attribute' : toPart}
  171.         exec(execString, d)
  172.         setattr(fromClass, method, d[method])   ### NEWU!


  173. class ScrolledCanvas(TK.Frame):
  174.     """Modeled after the scrolled canvas class from Grayons's Tkinter book.

  175.     Used as the default canvas, which pops up automatically when
  176.     using turtle graphics functions or the Turtle class.
  177.     """
  178.     def __init__(self, master, width=500, height=350,
  179.                                           canvwidth=600, canvheight=500):
  180.         TK.Frame.__init__(self, master, width=width, height=height)
  181.         self._rootwindow = self.winfo_toplevel()
  182.         self.width, self.height = width, height
  183.         self.canvwidth, self.canvheight = canvwidth, canvheight
  184.         self.bg = "white"
  185.         self._canvas = TK.Canvas(master, width=width, height=height,
  186.                                  bg=self.bg, relief=TK.SUNKEN, borderwidth=2)
  187.         self.hscroll = TK.Scrollbar(master, command=self._canvas.xview,
  188.                                     orient=TK.HORIZONTAL)
  189.         self.vscroll = TK.Scrollbar(master, command=self._canvas.yview)
  190.         self._canvas.configure(xscrollcommand=self.hscroll.set,
  191.                                yscrollcommand=self.vscroll.set)
  192.         self.rowconfigure(0, weight=1, minsize=0)
  193.         self.columnconfigure(0, weight=1, minsize=0)
  194.         self._canvas.grid(padx=1, in_ = self, pady=1, row=0,
  195.                 column=0, rowspan=1, columnspan=1, sticky='news')
  196.         self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
  197.                 column=1, rowspan=1, columnspan=1, sticky='news')
  198.         self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
  199.                 column=0, rowspan=1, columnspan=1, sticky='news')
  200.         self.reset()
  201.         self._rootwindow.bind('<Configure>', self.onResize)

  202.     def reset(self, canvwidth=None, canvheight=None, bg = None):
  203.         """Adjust canvas and scrollbars according to given canvas size."""
  204.         if canvwidth:
  205.             self.canvwidth = canvwidth
  206.         if canvheight:
  207.             self.canvheight = canvheight
  208.         if bg:
  209.             self.bg = bg
  210.         self._canvas.config(bg=bg,
  211.                         scrollregion=(-self.canvwidth//2, -self.canvheight//2,
  212.                                        self.canvwidth//2, self.canvheight//2))
  213.         self._canvas.xview_moveto(0.5*(self.canvwidth - self.width + 30) /
  214.                                                                self.canvwidth)
  215.         self._canvas.yview_moveto(0.5*(self.canvheight- self.height + 30) /
  216.                                                               self.canvheight)
  217.         self.adjustScrolls()


  218.     def adjustScrolls(self):
  219.         """ Adjust scrollbars according to window- and canvas-size.
  220.         """
  221.         cwidth = self._canvas.winfo_width()
  222.         cheight = self._canvas.winfo_height()
  223.         self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth)
  224.         self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight)
  225.         if cwidth < self.canvwidth or cheight < self.canvheight:
  226.             self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
  227.                               column=0, rowspan=1, columnspan=1, sticky='news')
  228.             self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
  229.                               column=1, rowspan=1, columnspan=1, sticky='news')
  230.         else:
  231.             self.hscroll.grid_forget()
  232.             self.vscroll.grid_forget()

  233.     def onResize(self, event):
  234.         """self-explanatory"""
  235.         self.adjustScrolls()

  236.     def bbox(self, *args):
  237.         """ 'forward' method, which canvas itself has inherited...
  238.         """
  239.         return self._canvas.bbox(*args)

  240.     def cget(self, *args, **kwargs):
  241.         """ 'forward' method, which canvas itself has inherited...
  242.         """
  243.         return self._canvas.cget(*args, **kwargs)

  244.     def config(self, *args, **kwargs):
  245.         """ 'forward' method, which canvas itself has inherited...
  246.         """
  247.         self._canvas.config(*args, **kwargs)

  248.     def bind(self, *args, **kwargs):
  249.         """ 'forward' method, which canvas itself has inherited...
  250.         """
  251.         self._canvas.bind(*args, **kwargs)

  252.     def unbind(self, *args, **kwargs):
  253.         """ 'forward' method, which canvas itself has inherited...
  254.         """
  255.         self._canvas.unbind(*args, **kwargs)

  256.     def focus_force(self):
  257.         """ 'forward' method, which canvas itself has inherited...
  258.         """
  259.         self._canvas.focus_force()

  260. __forwardmethods(ScrolledCanvas, TK.Canvas, '_canvas')


  261. class _Root(TK.Tk):
  262.     """Root class for Screen based on Tkinter."""
  263.     def __init__(self):
  264.         TK.Tk.__init__(self)

  265.     def setupcanvas(self, width, height, cwidth, cheight):
  266.         self._canvas = ScrolledCanvas(self, width, height, cwidth, cheight)
  267.         self._canvas.pack(expand=1, fill="both")

  268.     def _getcanvas(self):
  269.         return self._canvas

  270.     def set_geometry(self, width, height, startx, starty):
  271.         self.geometry("%dx%d%+d%+d"%(width, height, startx, starty))

  272.     def ondestroy(self, destroy):
  273.         self.wm_protocol("WM_DELETE_WINDOW", destroy)

  274.     def win_width(self):
  275.         return self.winfo_screenwidth()

  276.     def win_height(self):
  277.         return self.winfo_screenheight()

  278. Canvas = TK.Canvas


  279. class TurtleScreenBase(object):
  280.     @staticmethod
  281.     def _blankimage():
  282.         """return a blank image object
  283.         """
  284.         img = TK.PhotoImage(width=1, height=1)
  285.         img.blank()
  286.         return img

  287.     @staticmethod
  288.     def _image(filename):
  289.         """return an image object containing the
  290.         imagedata from a gif-file named filename.
  291.         """
  292.         return TK.PhotoImage(file=filename)

  293.     def __init__(self, cv):
  294.         self.cv = cv
  295.         if isinstance(cv, ScrolledCanvas):
  296.             w = self.cv.canvwidth
  297.             h = self.cv.canvheight
  298.         else:  # expected: ordinary TK.Canvas
  299.             w = int(self.cv.cget("width"))
  300.             h = int(self.cv.cget("height"))
  301.             self.cv.config(scrollregion = (-w//2, -h//2, w//2, h//2 ))
  302.         self.canvwidth = w
  303.         self.canvheight = h
  304.         self.xscale = self.yscale = 1.0

  305.     def _createpoly(self):
  306.         """Create an invisible polygon item on canvas self.cv)
  307.         """
  308.         return self.cv.create_polygon((0, 0, 0, 0, 0, 0), fill="", outline="")

  309.     def _drawpoly(self, polyitem, coordlist, fill=None,
  310.                   outline=None, width=None, top=False):
  311.         cl = []
  312.         for x, y in coordlist:
  313.             cl.append(x * self.xscale)
  314.             cl.append(-y * self.yscale)
  315.         self.cv.coords(polyitem, *cl)
  316.         if fill is not None:
  317.             self.cv.itemconfigure(polyitem, fill=fill)
  318.         if outline is not None:
  319.             self.cv.itemconfigure(polyitem, outline=outline)
  320.         if width is not None:
  321.             self.cv.itemconfigure(polyitem, width=width)
  322.         if top:
  323.             self.cv.tag_raise(polyitem)

  324.     def _createline(self):
  325.         """Create an invisible line item on canvas self.cv)
  326.         """
  327.         return self.cv.create_line(0, 0, 0, 0, fill="", width=2,
  328.                                    capstyle = TK.ROUND)

  329.     def _drawline(self, lineitem, coordlist=None,
  330.                   fill=None, width=None, top=False):
  331.         if coordlist is not None:
  332.             cl = []
  333.             for x, y in coordlist:
  334.                 cl.append(x * self.xscale)
  335.                 cl.append(-y * self.yscale)
  336.             self.cv.coords(lineitem, *cl)
  337.         if fill is not None:
  338.             self.cv.itemconfigure(lineitem, fill=fill)
  339.         if width is not None:
  340.             self.cv.itemconfigure(lineitem, width=width)
  341.         if top:
  342.             self.cv.tag_raise(lineitem)

  343.     def _delete(self, item):
  344.         self.cv.delete(item)

  345.     def _update(self):
  346.         """Redraw graphics items on canvas
  347.         """
  348.         self.cv.update()

  349.     def _delay(self, delay):
  350.         """Delay subsequent canvas actions for delay ms."""
  351.         self.cv.after(delay)

  352.     def _iscolorstring(self, color):
  353.         """Check if the string color is a legal Tkinter color string.
  354.         """
  355.         try:
  356.             rgb = self.cv.winfo_rgb(color)
  357.             ok = True
  358.         except TK.TclError:
  359.             ok = False
  360.         return ok

  361.     def _bgcolor(self, color=None):
  362.         if color is not None:
  363.             self.cv.config(bg = color)
  364.             self._update()
  365.         else:
  366.             return self.cv.cget("bg")

  367.     def _write(self, pos, txt, align, font, pencolor):
  368.         x, y = pos
  369.         x = x * self.xscale
  370.         y = y * self.yscale
  371.         anchor = {"left":"sw", "center":"s", "right":"se" }
  372.         item = self.cv.create_text(x-1, -y, text = txt, anchor = anchor[align],
  373.                                         fill = pencolor, font = font)
  374.         x0, y0, x1, y1 = self.cv.bbox(item)
  375.         self.cv.update()
  376.         return item, x1-1

  377. ##    def _dot(self, pos, size, color):
  378. ##        """may be implemented for some other graphics toolkit"""

  379.     def _onclick(self, item, fun, num=1, add=None):
  380.         """Bind fun to mouse-click event on turtle.
  381.         fun must be a function with two arguments, the coordinates
  382.         of the clicked point on the canvas.
  383.         num, the number of the mouse-button defaults to 1
  384.         """
  385.         if fun is None:
  386.             self.cv.tag_unbind(item, "<Button-%s>" % num)
  387.         else:
  388.             def eventfun(event):
  389.                 x, y = (self.cv.canvasx(event.x)/self.xscale,
  390.                         -self.cv.canvasy(event.y)/self.yscale)
  391.                 fun(x, y)
  392.             self.cv.tag_bind(item, "<Button-%s>" % num, eventfun, add)

  393.     def _onrelease(self, item, fun, num=1, add=None):
  394.         if fun is None:
  395.             self.cv.tag_unbind(item, "<Button%s-ButtonRelease>" % num)
  396.         else:
  397.             def eventfun(event):
  398.                 x, y = (self.cv.canvasx(event.x)/self.xscale,
  399.                         -self.cv.canvasy(event.y)/self.yscale)
  400.                 fun(x, y)
  401.             self.cv.tag_bind(item, "<Button%s-ButtonRelease>" % num,
  402.                              eventfun, add)

  403.     def _ondrag(self, item, fun, num=1, add=None):
  404.         """Bind fun to mouse-move-event (with pressed mouse button) on turtle.
  405.         fun must be a function with two arguments, the coordinates of the
  406.         actual mouse position on the canvas.
  407.         num, the number of the mouse-button defaults to 1

  408.         Every sequence of mouse-move-events on a turtle is preceded by a
  409.         mouse-click event on that turtle.
  410.         """
  411.         if fun is None:
  412.             self.cv.tag_unbind(item, "<Button%s-Motion>" % num)
  413.         else:
  414.             def eventfun(event):
  415.                 try:
  416.                     x, y = (self.cv.canvasx(event.x)/self.xscale,
  417.                            -self.cv.canvasy(event.y)/self.yscale)
  418.                     fun(x, y)
  419.                 except Exception:
  420.                     pass
  421.             self.cv.tag_bind(item, "<Button%s-Motion>" % num, eventfun, add)

  422.     def _onscreenclick(self, fun, num=1, add=None):
  423.         if fun is None:
  424.             self.cv.unbind("<Button-%s>" % num)
  425.         else:
  426.             def eventfun(event):
  427.                 x, y = (self.cv.canvasx(event.x)/self.xscale,
  428.                         -self.cv.canvasy(event.y)/self.yscale)
  429.                 fun(x, y)
  430.             self.cv.bind("<Button-%s>" % num, eventfun, add)

  431.     def _onkeyrelease(self, fun, key):
  432.         """Bind fun to key-release event of key.
  433.         Canvas must have focus. See method listen
  434.         """
  435.         if fun is None:
  436.             self.cv.unbind("<KeyRelease-%s>" % key, None)
  437.         else:
  438.             def eventfun(event):
  439.                 fun()
  440.             self.cv.bind("<KeyRelease-%s>" % key, eventfun)

  441.     def _onkeypress(self, fun, key=None):
  442.         """If key is given, bind fun to key-press event of key.
  443.         Otherwise bind fun to any key-press.
  444.         Canvas must have focus. See method listen.
  445.         """
  446.         if fun is None:
  447.             if key is None:
  448.                 self.cv.unbind("<KeyPress>", None)
  449.             else:
  450.                 self.cv.unbind("<KeyPress-%s>" % key, None)
  451.         else:
  452.             def eventfun(event):
  453.                 fun()
  454.             if key is None:
  455.                 self.cv.bind("<KeyPress>", eventfun)
  456.             else:
  457.                 self.cv.bind("<KeyPress-%s>" % key, eventfun)

  458.     def _listen(self):
  459.         """Set focus on canvas (in order to collect key-events)
  460.         """
  461.         self.cv.focus_force()

  462.     def _ontimer(self, fun, t):
  463.         """Install a timer, which calls fun after t milliseconds.
  464.         """
  465.         if t == 0:
  466.             self.cv.after_idle(fun)
  467.         else:
  468.             self.cv.after(t, fun)

  469.     def _createimage(self, image):
  470.         """Create and return image item on canvas.
  471.         """
  472.         return self.cv.create_image(0, 0, image=image)

  473.     def _drawimage(self, item, pos, image):
  474.         """Configure image item as to draw image object
  475.         at position (x,y) on canvas)
  476.         """
  477.         x, y = pos
  478.         self.cv.coords(item, (x * self.xscale, -y * self.yscale))
  479.         self.cv.itemconfig(item, image=image)

  480.     def _setbgpic(self, item, image):
  481.         """Configure image item as to draw image object
  482.         at center of canvas. Set item to the first item
  483.         in the displaylist, so it will be drawn below
  484.         any other item ."""
  485.         self.cv.itemconfig(item, image=image)
  486.         self.cv.tag_lower(item)

  487.     def _type(self, item):
  488.         """Return 'line' or 'polygon' or 'image' depending on
  489.         type of item.
  490.         """
  491.         return self.cv.type(item)

  492.     def _pointlist(self, item):
  493.         """returns list of coordinate-pairs of points of item
  494.         Example (for insiders):
  495.         >>> from turtle import *
  496.         >>> getscreen()._pointlist(getturtle().turtle._item)
  497.         [(0.0, 9.9999999999999982), (0.0, -9.9999999999999982),
  498.         (9.9999999999999982, 0.0)]
  499.         >>> """
  500.         cl = self.cv.coords(item)
  501.         pl = [(cl[i], -cl[i+1]) for i in range(0, len(cl), 2)]
  502.         return  pl

  503.     def _setscrollregion(self, srx1, sry1, srx2, sry2):
  504.         self.cv.config(scrollregion=(srx1, sry1, srx2, sry2))

  505.     def _rescale(self, xscalefactor, yscalefactor):
  506.         items = self.cv.find_all()
  507.         for item in items:
  508.             coordinates = list(self.cv.coords(item))
  509.             newcoordlist = []
  510.             while coordinates:
  511.                 x, y = coordinates[:2]
  512.                 newcoordlist.append(x * xscalefactor)
  513.                 newcoordlist.append(y * yscalefactor)
  514.                 coordinates = coordinates[2:]
  515.             self.cv.coords(item, *newcoordlist)

  516.     def _resize(self, canvwidth=None, canvheight=None, bg=None):
  517.         """Resize the canvas the turtles are drawing on. Does
  518.         not alter the drawing window.
  519.         """
  520.         # needs amendment
  521.         if not isinstance(self.cv, ScrolledCanvas):
  522.             return self.canvwidth, self.canvheight
  523.         if canvwidth is canvheight is bg is None:
  524.             return self.cv.canvwidth, self.cv.canvheight
  525.         if canvwidth is not None:
  526.             self.canvwidth = canvwidth
  527.         if canvheight is not None:
  528.             self.canvheight = canvheight
  529.         self.cv.reset(canvwidth, canvheight, bg)

  530.     def _window_size(self):
  531.         """ Return the width and height of the turtle window.
  532.         """
  533.         width = self.cv.winfo_width()
  534.         if width <= 1:
  535.             width = self.cv['width']
  536.         height = self.cv.winfo_height()
  537.         if height <= 1:
  538.             height = self.cv['height']
  539.         return width, height

  540.     def mainloop(self):
  541.         TK.mainloop()

  542.     def textinput(self, title, prompt):
  543.         return simpledialog.askstring(title, prompt)

  544.     def numinput(self, title, prompt, default=None, minval=None, maxval=None):
  545.         return simpledialog.askfloat(title, prompt, initialvalue=default,
  546.                                      minvalue=minval, maxvalue=maxval)

  547. class Terminator (Exception):
  548.     pass


  549. class TurtleGraphicsError(Exception):
  550.     """Some TurtleGraphics Error
  551.     """


  552. class Shape(object):
  553.     def __init__(self, type_, data=None):
  554.         self._type = type_
  555.         if type_ == "polygon":
  556.             if isinstance(data, list):
  557.                 data = tuple(data)
  558.         elif type_ == "image":
  559.             if isinstance(data, str):
  560.                 if data.lower().endswith(".gif") and isfile(data):
  561.                     data = TurtleScreen._image(data)
  562.                 # else data assumed to be Photoimage
  563.         elif type_ == "compound":
  564.             data = []
  565.         else:
  566.             raise TurtleGraphicsError("There is no shape type %s" % type_)
  567.         self._data = data

  568.     def addcomponent(self, poly, fill, outline=None):
  569.         if self._type != "compound":
  570.             raise TurtleGraphicsError("Cannot add component to %s Shape"
  571.                                                                 % self._type)
  572.         if outline is None:
  573.             outline = fill
  574.         self._data.append([poly, fill, outline])


  575. class Tbuffer(object):
  576.     """Ring buffer used as undobuffer for RawTurtle objects."""
  577.     def __init__(self, bufsize=10):
  578.         self.bufsize = bufsize
  579.         self.buffer = [[None]] * bufsize
  580.         self.ptr = -1
  581.         self.cumulate = False
  582.     def reset(self, bufsize=None):
  583.         if bufsize is None:
  584.             for i in range(self.bufsize):
  585.                 self.buffer[i] = [None]
  586.         else:
  587.             self.bufsize = bufsize
  588.             self.buffer = [[None]] * bufsize
  589.         self.ptr = -1
  590.     def push(self, item):
  591.         if self.bufsize > 0:
  592.             if not self.cumulate:
  593.                 self.ptr = (self.ptr + 1) % self.bufsize
  594.                 self.buffer[self.ptr] = item
  595.             else:
  596.                 self.buffer[self.ptr].append(item)
  597.     def pop(self):
  598.         if self.bufsize > 0:
  599.             item = self.buffer[self.ptr]
  600.             if item is None:
  601.                 return None
  602.             else:
  603.                 self.buffer[self.ptr] = [None]
  604.                 self.ptr = (self.ptr - 1) % self.bufsize
  605.                 return (item)
  606.     def nr_of_items(self):
  607.         return self.bufsize - self.buffer.count([None])
  608.     def __repr__(self):
  609.         return str(self.buffer) + " " + str(self.ptr)



  610. class TurtleScreen(TurtleScreenBase):
  611.     _RUNNING = True

  612.     def __init__(self, cv, mode=_CFG["mode"],
  613.                  colormode=_CFG["colormode"], delay=_CFG["delay"]):
  614.         self._shapes = {
  615.                    "arrow" : Shape("polygon", ((-10,0), (10,0), (0,10))),
  616.                   "turtle" : Shape("polygon", ((0,16), (-2,14), (-1,10), (-4,7),
  617.                               (-7,9), (-9,8), (-6,5), (-7,1), (-5,-3), (-8,-6),
  618.                               (-6,-8), (-4,-5), (0,-7), (4,-5), (6,-8), (8,-6),
  619.                               (5,-3), (7,1), (6,5), (9,8), (7,9), (4,7), (1,10),
  620.                               (2,14))),
  621.                   "circle" : Shape("polygon", ((10,0), (9.51,3.09), (8.09,5.88),
  622.                               (5.88,8.09), (3.09,9.51), (0,10), (-3.09,9.51),
  623.                               (-5.88,8.09), (-8.09,5.88), (-9.51,3.09), (-10,0),
  624.                               (-9.51,-3.09), (-8.09,-5.88), (-5.88,-8.09),
  625.                               (-3.09,-9.51), (-0.00,-10.00), (3.09,-9.51),
  626.                               (5.88,-8.09), (8.09,-5.88), (9.51,-3.09))),
  627.                   "square" : Shape("polygon", ((10,-10), (10,10), (-10,10),
  628.                               (-10,-10))),
  629.                 "triangle" : Shape("polygon", ((10,-5.77), (0,11.55),
  630.                               (-10,-5.77))),
  631.                   "classic": Shape("polygon", ((0,0),(-5,-9),(0,-7),(5,-9))),
  632.                    "blank" : Shape("image", self._blankimage())
  633.                   }

  634.         self._bgpics = {"nopic" : ""}

  635.         TurtleScreenBase.__init__(self, cv)
  636.         self._mode = mode
  637.         self._delayvalue = delay
  638.         self._colormode = _CFG["colormode"]
  639.         self._keys = []
  640.         self.clear()
  641.         if sys.platform == 'darwin':
  642.             rootwindow = cv.winfo_toplevel()
  643.             rootwindow.call('wm', 'attributes', '.', '-topmost', '1')
  644.             rootwindow.call('wm', 'attributes', '.', '-topmost', '0')

  645.     def clear(self):
  646.         self._delayvalue = _CFG["delay"]
  647.         self._colormode = _CFG["colormode"]
  648.         self._delete("all")
  649.         self._bgpic = self._createimage("")
  650.         self._bgpicname = "nopic"
  651.         self._tracing = 1
  652.         self._updatecounter = 0
  653.         self._turtles = []
  654.         self.bgcolor("white")
  655.         for btn in 1, 2, 3:
  656.             self.onclick(None, btn)
  657.         self.onkeypress(None)
  658.         for key in self._keys[:]:
  659.             self.onkey(None, key)
  660.             self.onkeypress(None, key)
  661.         Turtle._pen = None

  662.     def mode(self, mode=None):
  663.         if mode is None:
  664.             return self._mode
  665.         mode = mode.lower()
  666.         if mode not in ["standard", "logo", "world"]:
  667.             raise TurtleGraphicsError("No turtle-graphics-mode %s" % mode)
  668.         self._mode = mode
  669.         if mode in ["standard", "logo"]:
  670.             self._setscrollregion(-self.canvwidth//2, -self.canvheight//2,
  671.                                        self.canvwidth//2, self.canvheight//2)
  672.             self.xscale = self.yscale = 1.0
  673.         self.reset()

  674.     def setworldcoordinates(self, llx, lly, urx, ury):
  675.         if self.mode() != "world":
  676.             self.mode("world")
  677.         xspan = float(urx - llx)
  678.         yspan = float(ury - lly)
  679.         wx, wy = self._window_size()
  680.         self.screensize(wx-20, wy-20)
  681.         oldxscale, oldyscale = self.xscale, self.yscale
  682.         self.xscale = self.canvwidth / xspan
  683.         self.yscale = self.canvheight / yspan
  684.         srx1 = llx * self.xscale
  685.         sry1 = -ury * self.yscale
  686.         srx2 = self.canvwidth + srx1
  687.         sry2 = self.canvheight + sry1
  688.         self._setscrollregion(srx1, sry1, srx2, sry2)
  689.         self._rescale(self.xscale/oldxscale, self.yscale/oldyscale)
  690.         self.update()

  691.     def register_shape(self, name, shape=None):
  692.         if shape is None:
  693.             # image
  694.             if name.lower().endswith(".gif"):
  695.                 shape = Shape("image", self._image(name))
  696.             else:
  697.                 raise TurtleGraphicsError("Bad arguments for register_shape.\n"
  698.                                           + "Use  help(register_shape)" )
  699.         elif isinstance(shape, tuple):
  700.             shape = Shape("polygon", shape)
  701.         ## else shape assumed to be Shape-instance
  702.         self._shapes[name] = shape

  703.     def _colorstr(self, color):
  704.         if len(color) == 1:
  705.             color = color[0]
  706.         if isinstance(color, str):
  707.             if self._iscolorstring(color) or color == "":
  708.                 return color
  709.             else:
  710.                 raise TurtleGraphicsError("bad color string: %s" % str(color))
  711.         try:
  712.             r, g, b = color
  713.         except (TypeError, ValueError):
  714.             raise TurtleGraphicsError("bad color arguments: %s" % str(color))
  715.         if self._colormode == 1.0:
  716.             r, g, b = [round(255.0*x) for x in (r, g, b)]
  717.         if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
  718.             raise TurtleGraphicsError("bad color sequence: %s" % str(color))
  719.         return "#%02x%02x%02x" % (r, g, b)

  720.     def _color(self, cstr):
  721.         if not cstr.startswith("#"):
  722.             return cstr
  723.         if len(cstr) == 7:
  724.             cl = [int(cstr[i:i+2], 16) for i in (1, 3, 5)]
  725.         elif len(cstr) == 4:
  726.             cl = [16*int(cstr[h], 16) for h in cstr[1:]]
  727.         else:
  728.             raise TurtleGraphicsError("bad colorstring: %s" % cstr)
  729.         return tuple(c * self._colormode/255 for c in cl)

  730.     def colormode(self, cmode=None):
  731.         if cmode is None:
  732.             return self._colormode
  733.         if cmode == 1.0:
  734.             self._colormode = float(cmode)
  735.         elif cmode == 255:
  736.             self._colormode = int(cmode)

  737.     def reset(self):
  738.         for turtle in self._turtles:
  739.             turtle._setmode(self._mode)
  740.             turtle.reset()

  741.     def turtles(self):
  742.         return self._turtles

  743.     def bgcolor(self, *args):
  744.         if args:
  745.             color = self._colorstr(args)
  746.         else:
  747.             color = None
  748.         color = self._bgcolor(color)
  749.         if color is not None:
  750.             color = self._color(color)
  751.         return color

  752.     def tracer(self, n=None, delay=None):
  753.         if n is None:
  754.             return self._tracing
  755.         self._tracing = int(n)
  756.         self._updatecounter = 0
  757.         if delay is not None:
  758.             self._delayvalue = int(delay)
  759.         if self._tracing:
  760.             self.update()

  761.     def delay(self, delay=None):
  762.         if delay is None:
  763.             return self._delayvalue
  764.         self._delayvalue = int(delay)

  765.     def _incrementudc(self):
  766.         """Increment update counter."""
  767.         if not TurtleScreen._RUNNING:
  768.             TurtleScreen._RUNNING = True
  769.             raise Terminator
  770.         if self._tracing > 0:
  771.             self._updatecounter += 1
  772.             self._updatecounter %= self._tracing

  773.     def update(self):
  774.         """Perform a TurtleScreen update.
  775.         """
  776.         tracing = self._tracing
  777.         self._tracing = True
  778.         for t in self.turtles():
  779.             t._update_data()
  780.             t._drawturtle()
  781.         self._tracing = tracing
  782.         self._update()

  783.     def window_width(self):
  784.         return self._window_size()[0]

  785.     def window_height(self):
  786.         return self._window_size()[1]

  787.     def getcanvas(self):
  788.         return self.cv

  789.     def getshapes(self):
  790.         return sorted(self._shapes.keys())

  791.     def onclick(self, fun, btn=1, add=None):
  792.         self._onscreenclick(fun, btn, add)

  793.     def onkey(self, fun, key):
  794.         if fun is None:
  795.             if key in self._keys:
  796.                 self._keys.remove(key)
  797.         elif key not in self._keys:
  798.             self._keys.append(key)
  799.         self._onkeyrelease(fun, key)

  800.     def onkeypress(self, fun, key=None):
  801.         if fun is None:
  802.             if key in self._keys:
  803.                 self._keys.remove(key)
  804.         elif key is not None and key not in self._keys:
  805.             self._keys.append(key)
  806.         self._onkeypress(fun, key)

  807.     def listen(self, xdummy=None, ydummy=None):
  808.         self._listen()

  809.     def ontimer(self, fun, t=0):
  810.         self._ontimer(fun, t)

  811.     def bgpic(self, picname=None):
  812.         if picname is None:
  813.             return self._bgpicname
  814.         if picname not in self._bgpics:
  815.             self._bgpics[picname] = self._image(picname)
  816.         self._setbgpic(self._bgpic, self._bgpics[picname])
  817.         self._bgpicname = picname

  818.     def screensize(self, canvwidth=None, canvheight=None, bg=None):
  819.         return self._resize(canvwidth, canvheight, bg)

  820.     onscreenclick = onclick
  821.     resetscreen = reset
  822.     clearscreen = clear
  823.     addshape = register_shape
  824.     onkeyrelease = onkey

  825. class TNavigator(object):
  826.     """Navigation part of the RawTurtle.
  827.     Implements methods for turtle movement.
  828.     """
  829.     START_ORIENTATION = {
  830.         "standard": Vec2D(1.0, 0.0),
  831.         "world"   : Vec2D(1.0, 0.0),
  832.         "logo"    : Vec2D(0.0, 1.0)  }
  833.     DEFAULT_MODE = "standard"
  834.     DEFAULT_ANGLEOFFSET = 0
  835.     DEFAULT_ANGLEORIENT = 1

  836.     def __init__(self, mode=DEFAULT_MODE):
  837.         self._angleOffset = self.DEFAULT_ANGLEOFFSET
  838.         self._angleOrient = self.DEFAULT_ANGLEORIENT
  839.         self._mode = mode
  840.         self.undobuffer = None
  841.         self.degrees()
  842.         self._mode = None
  843.         self._setmode(mode)
  844.         TNavigator.reset(self)

  845.     def reset(self):
  846.         self._position = Vec2D(0.0, 0.0)
  847.         self._orient =  TNavigator.START_ORIENTATION[self._mode]

  848.     def _setmode(self, mode=None):
  849.         """Set turtle-mode to 'standard', 'world' or 'logo'.
  850.         """
  851.         if mode is None:
  852.             return self._mode
  853.         if mode not in ["standard", "logo", "world"]:
  854.             return
  855.         self._mode = mode
  856.         if mode in ["standard", "world"]:
  857.             self._angleOffset = 0
  858.             self._angleOrient = 1
  859.         else: # mode == "logo":
  860.             self._angleOffset = self._fullcircle/4.
  861.             self._angleOrient = -1

  862.     def _setDegreesPerAU(self, fullcircle):
  863.         """Helper function for degrees() and radians()"""
  864.         self._fullcircle = fullcircle
  865.         self._degreesPerAU = 360/fullcircle
  866.         if self._mode == "standard":
  867.             self._angleOffset = 0
  868.         else:
  869.             self._angleOffset = fullcircle/4.

  870.     def degrees(self, fullcircle=360.0):
  871.         self._setDegreesPerAU(fullcircle)

  872.     def radians(self):
  873.         self._setDegreesPerAU(2*math.pi)

  874.     def _go(self, distance):
  875.         """move turtle forward by specified distance"""
  876.         ende = self._position + self._orient * distance
  877.         self._goto(ende)

  878.     def _rotate(self, angle):
  879.         """Turn turtle counterclockwise by specified angle if angle > 0."""
  880.         angle *= self._degreesPerAU
  881.         self._orient = self._orient.rotate(angle)

  882.     def _goto(self, end):
  883.         """move turtle to position end."""
  884.         self._position = end

  885.     def forward(self, distance):
  886.         self._go(distance)

  887.     def back(self, distance):
  888.         self._go(-distance)

  889.     def right(self, angle):
  890.         self._rotate(-angle)

  891.     def left(self, angle):
  892.         self._rotate(angle)

  893.     def pos(self):
  894.         return self._position

  895.     def xcor(self):
  896.         return self._position[0]

  897.     def ycor(self):
  898.         return self._position[1]


  899.     def goto(self, x, y=None):
  900.         if y is None:
  901.             self._goto(Vec2D(*x))
  902.         else:
  903.             self._goto(Vec2D(x, y))

  904.     def home(self):
  905.         self.goto(0, 0)
  906.         self.setheading(0)

  907.     def setx(self, x):
  908.         self._goto(Vec2D(x, self._position[1]))

  909.     def sety(self, y):
  910.         self._goto(Vec2D(self._position[0], y))

  911.     def distance(self, x, y=None):
  912.         if y is not None:
  913.             pos = Vec2D(x, y)
  914.         if isinstance(x, Vec2D):
  915.             pos = x
  916.         elif isinstance(x, tuple):
  917.             pos = Vec2D(*x)
  918.         elif isinstance(x, TNavigator):
  919.             pos = x._position
  920.         return abs(pos - self._position)

  921.     def towards(self, x, y=None):
  922.         if y is not None:
  923.             pos = Vec2D(x, y)
  924.         if isinstance(x, Vec2D):
  925.             pos = x
  926.         elif isinstance(x, tuple):
  927.             pos = Vec2D(*x)
  928.         elif isinstance(x, TNavigator):
  929.             pos = x._position
  930.         x, y = pos - self._position
  931.         result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
  932.         result /= self._degreesPerAU
  933.         return (self._angleOffset + self._angleOrient*result) % self._fullcircle

  934.     def heading(self):
  935.         x, y = self._orient
  936.         result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
  937.         result /= self._degreesPerAU
  938.         return (self._angleOffset + self._angleOrient*result) % self._fullcircle

  939.     def setheading(self, to_angle):
  940.         angle = (to_angle - self.heading())*self._angleOrient
  941.         full = self._fullcircle
  942.         angle = (angle+full/2.)%full - full/2.
  943.         self._rotate(angle)

  944.     def circle(self, radius, extent = None, steps = None):
  945.         if self.undobuffer:
  946.             self.undobuffer.push(["seq"])
  947.             self.undobuffer.cumulate = True
  948.         speed = self.speed()
  949.         if extent is None:
  950.             extent = self._fullcircle
  951.         if steps is None:
  952.             frac = abs(extent)/self._fullcircle
  953.             steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac)
  954.         w = 1.0 * extent / steps
  955.         w2 = 0.5 * w
  956.         l = 2.0 * radius * math.sin(w2*math.pi/180.0*self._degreesPerAU)
  957.         if radius < 0:
  958.             l, w, w2 = -l, -w, -w2
  959.         tr = self._tracer()
  960.         dl = self._delay()
  961.         if speed == 0:
  962.             self._tracer(0, 0)
  963.         else:
  964.             self.speed(0)
  965.         self._rotate(w2)
  966.         for i in range(steps):
  967.             self.speed(speed)
  968.             self._go(l)
  969.             self.speed(0)
  970.             self._rotate(w)
  971.         self._rotate(-w2)
  972.         if speed == 0:
  973.             self._tracer(tr, dl)
  974.         self.speed(speed)
  975.         if self.undobuffer:
  976.             self.undobuffer.cumulate = False

  977. ## three dummy methods to be implemented by child class:

  978.     def speed(self, s=0):
  979.         """dummy method - to be overwritten by child class"""
  980.     def _tracer(self, a=None, b=None):
  981.         """dummy method - to be overwritten by child class"""
  982.     def _delay(self, n=None):
  983.         """dummy method - to be overwritten by child class"""

  984.     fd = forward
  985.     bk = back
  986.     backward = back
  987.     rt = right
  988.     lt = left
  989.     position = pos
  990.     setpos = goto
  991.     setposition = goto
  992.     seth = setheading


  993. class TPen(object):
  994.     def __init__(self, resizemode=_CFG["resizemode"]):
  995.         self._resizemode = resizemode # or "user" or "noresize"
  996.         self.undobuffer = None
  997.         TPen._reset(self)

  998.     def _reset(self, pencolor=_CFG["pencolor"],
  999.                      fillcolor=_CFG["fillcolor"]):
  1000.         self._pensize = 1
  1001.         self._shown = True
  1002.         self._pencolor = pencolor
  1003.         self._fillcolor = fillcolor
  1004.         self._drawing = True
  1005.         self._speed = 3
  1006.         self._stretchfactor = (1., 1.)
  1007.         self._shearfactor = 0.
  1008.         self._tilt = 0.
  1009.         self._shapetrafo = (1., 0., 0., 1.)
  1010.         self._outlinewidth = 1

  1011.     def resizemode(self, rmode=None):
  1012.         if rmode is None:
  1013.             return self._resizemode
  1014.         rmode = rmode.lower()
  1015.         if rmode in ["auto", "user", "noresize"]:
  1016.             self.pen(resizemode=rmode)

  1017.     def pensize(self, width=None):
  1018.         if width is None:
  1019.             return self._pensize
  1020.         self.pen(pensize=width)


  1021.     def penup(self):
  1022.         if not self._drawing:
  1023.             return
  1024.         self.pen(pendown=False)

  1025.     def pendown(self):
  1026.         if self._drawing:
  1027.             return
  1028.         self.pen(pendown=True)

  1029.     def isdown(self):
  1030.         return self._drawing

  1031.     def speed(self, speed=None):
  1032.         speeds = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 }
  1033.         if speed is None:
  1034.             return self._speed
  1035.         if speed in speeds:
  1036.             speed = speeds[speed]
  1037.         elif 0.5 < speed < 10.5:
  1038.             speed = int(round(speed))
  1039.         else:
  1040.             speed = 0
  1041.         self.pen(speed=speed)

  1042.     def color(self, *args):
  1043.         if args:
  1044.             l = len(args)
  1045.             if l == 1:
  1046.                 pcolor = fcolor = args[0]
  1047.             elif l == 2:
  1048.                 pcolor, fcolor = args
  1049.             elif l == 3:
  1050.                 pcolor = fcolor = args
  1051.             pcolor = self._colorstr(pcolor)
  1052.             fcolor = self._colorstr(fcolor)
  1053.             self.pen(pencolor=pcolor, fillcolor=fcolor)
  1054.         else:
  1055.             return self._color(self._pencolor), self._color(self._fillcolor)

  1056.     def pencolor(self, *args):
  1057.         if args:
  1058.             color = self._colorstr(args)
  1059.             if color == self._pencolor:
  1060.                 return
  1061.             self.pen(pencolor=color)
  1062.         else:
  1063.             return self._color(self._pencolor)

  1064.     def fillcolor(self, *args):
  1065.         if args:
  1066.             color = self._colorstr(args)
  1067.             if color == self._fillcolor:
  1068.                 return
  1069.             self.pen(fillcolor=color)
  1070.         else:
  1071.             return self._color(self._fillcolor)

  1072.     def showturtle(self):
  1073.         self.pen(shown=True)

  1074.     def hideturtle(self):
  1075.         self.pen(shown=False)

  1076.     def isvisible(self):
  1077.         return self._shown

  1078.     def pen(self, pen=None, **pendict):
  1079.         _pd =  {"shown"         : self._shown,
  1080.                 "pendown"       : self._drawing,
  1081.                 "pencolor"      : self._pencolor,
  1082.                 "fillcolor"     : self._fillcolor,
  1083.                 "pensize"       : self._pensize,
  1084.                 "speed"         : self._speed,
  1085.                 "resizemode"    : self._resizemode,
  1086.                 "stretchfactor" : self._stretchfactor,
  1087.                 "shearfactor"   : self._shearfactor,
  1088.                 "outline"       : self._outlinewidth,
  1089.                 "tilt"          : self._tilt
  1090.                }

  1091.         if not (pen or pendict):
  1092.             return _pd

  1093.         if isinstance(pen, dict):
  1094.             p = pen
  1095.         else:
  1096.             p = {}
  1097.         p.update(pendict)

  1098.         _p_buf = {}
  1099.         for key in p:
  1100.             _p_buf[key] = _pd[key]

  1101.         if self.undobuffer:
  1102.             self.undobuffer.push(("pen", _p_buf))

  1103.         newLine = False
  1104.         if "pendown" in p:
  1105.             if self._drawing != p["pendown"]:
  1106.                 newLine = True
  1107.         if "pencolor" in p:
  1108.             if isinstance(p["pencolor"], tuple):
  1109.                 p["pencolor"] = self._colorstr((p["pencolor"],))
  1110.             if self._pencolor != p["pencolor"]:
  1111.                 newLine = True
  1112.         if "pensize" in p:
  1113.             if self._pensize != p["pensize"]:
  1114.                 newLine = True
  1115.         if newLine:
  1116.             self._newLine()
  1117.         if "pendown" in p:
  1118.             self._drawing = p["pendown"]
  1119.         if "pencolor" in p:
  1120.             self._pencolor = p["pencolor"]
  1121.         if "pensize" in p:
  1122.             self._pensize = p["pensize"]
  1123.         if "fillcolor" in p:
  1124.             if isinstance(p["fillcolor"], tuple):
  1125.                 p["fillcolor"] = self._colorstr((p["fillcolor"],))
  1126.             self._fillcolor = p["fillcolor"]
  1127.         if "speed" in p:
  1128.             self._speed = p["speed"]
  1129.         if "resizemode" in p:
  1130.             self._resizemode = p["resizemode"]
  1131.         if "stretchfactor" in p:
  1132.             sf = p["stretchfactor"]
  1133.             if isinstance(sf, (int, float)):
  1134.                 sf = (sf, sf)
  1135.             self._stretchfactor = sf
  1136.         if "shearfactor" in p:
  1137.             self._shearfactor = p["shearfactor"]
  1138.         if "outline" in p:
  1139.             self._outlinewidth = p["outline"]
  1140.         if "shown" in p:
  1141.             self._shown = p["shown"]
  1142.         if "tilt" in p:
  1143.             self._tilt = p["tilt"]
  1144.         if "stretchfactor" in p or "tilt" in p or "shearfactor" in p:
  1145.             scx, scy = self._stretchfactor
  1146.             shf = self._shearfactor
  1147.             sa, ca = math.sin(self._tilt), math.cos(self._tilt)
  1148.             self._shapetrafo = ( scx*ca, scy*(shf*ca + sa),
  1149.                                 -scx*sa, scy*(ca - shf*sa))
  1150.         self._update()

  1151. ## three dummy methods to be implemented by child class:

  1152.     def _newLine(self, usePos = True):
  1153.         """dummy method - to be overwritten by child class"""
  1154.     def _update(self, count=True, forced=False):
  1155.         """dummy method - to be overwritten by child class"""
  1156.     def _color(self, args):
  1157.         """dummy method - to be overwritten by child class"""
  1158.     def _colorstr(self, args):
  1159.         """dummy method - to be overwritten by child class"""

  1160.     width = pensize
  1161.     up = penup
  1162.     pu = penup
  1163.     pd = pendown
  1164.     down = pendown
  1165.     st = showturtle
  1166.     ht = hideturtle


  1167. class _TurtleImage(object):
  1168.     """Helper class: Datatype to store Turtle attributes
  1169.     """

  1170.     def __init__(self, screen, shapeIndex):
  1171.         self.screen = screen
  1172.         self._type = None
  1173.         self._setshape(shapeIndex)

  1174.     def _setshape(self, shapeIndex):
  1175.         screen = self.screen
  1176.         self.shapeIndex = shapeIndex
  1177.         if self._type == "polygon" == screen._shapes[shapeIndex]._type:
  1178.             return
  1179.         if self._type == "image" == screen._shapes[shapeIndex]._type:
  1180.             return
  1181.         if self._type in ["image", "polygon"]:
  1182.             screen._delete(self._item)
  1183.         elif self._type == "compound":
  1184.             for item in self._item:
  1185.                 screen._delete(item)
  1186.         self._type = screen._shapes[shapeIndex]._type
  1187.         if self._type == "polygon":
  1188.             self._item = screen._createpoly()
  1189.         elif self._type == "image":
  1190.             self._item = screen._createimage(screen._shapes["blank"]._data)
  1191.         elif self._type == "compound":
  1192.             self._item = [screen._createpoly() for item in
  1193.                                           screen._shapes[shapeIndex]._data]


  1194. class RawTurtle(TPen, TNavigator):
  1195.     """Animation part of the RawTurtle.
  1196.     Puts RawTurtle upon a TurtleScreen and provides tools for
  1197.     its animation.
  1198.     """
  1199.     screens = []

  1200.     def __init__(self, canvas=None,
  1201.                  shape=_CFG["shape"],
  1202.                  undobuffersize=_CFG["undobuffersize"],
  1203.                  visible=_CFG["visible"]):
  1204.         if isinstance(canvas, _Screen):
  1205.             self.screen = canvas
  1206.         elif isinstance(canvas, TurtleScreen):
  1207.             if canvas not in RawTurtle.screens:
  1208.                 RawTurtle.screens.append(canvas)
  1209.             self.screen = canvas
  1210.         elif isinstance(canvas, (ScrolledCanvas, Canvas)):
  1211.             for screen in RawTurtle.screens:
  1212.                 if screen.cv == canvas:
  1213.                     self.screen = screen
  1214.                     break
  1215.             else:
  1216.                 self.screen = TurtleScreen(canvas)
  1217.                 RawTurtle.screens.append(self.screen)
  1218.         else:
  1219.             raise TurtleGraphicsError("bad canvas argument %s" % canvas)

  1220.         screen = self.screen
  1221.         TNavigator.__init__(self, screen.mode())
  1222.         TPen.__init__(self)
  1223.         screen._turtles.append(self)
  1224.         self.drawingLineItem = screen._createline()
  1225.         self.turtle = _TurtleImage(screen, shape)
  1226.         self._poly = None
  1227.         self._creatingPoly = False
  1228.         self._fillitem = self._fillpath = None
  1229.         self._shown = visible
  1230.         self._hidden_from_screen = False
  1231.         self.currentLineItem = screen._createline()
  1232.         self.currentLine = [self._position]
  1233.         self.items = [self.currentLineItem]
  1234.         self.stampItems = []
  1235.         self._undobuffersize = undobuffersize
  1236.         self.undobuffer = Tbuffer(undobuffersize)
  1237.         self._update()

  1238.     def reset(self):
  1239.         """Delete the turtle's drawings and restore its default values.

  1240.         No argument.

  1241.         Delete the turtle's drawings from the screen, re-center the turtle
  1242.         and set variables to the default values.

  1243.         Example (for a Turtle instance named turtle):
  1244.         >>> turtle.position()
  1245.         (0.00,-22.00)
  1246.         >>> turtle.heading()
  1247.         100.0
  1248.         >>> turtle.reset()
  1249.         >>> turtle.position()
  1250.         (0.00,0.00)
  1251.         >>> turtle.heading()
  1252.         0.0
  1253.         """
  1254.         TNavigator.reset(self)
  1255.         TPen._reset(self)
  1256.         self._clear()
  1257.         self._drawturtle()
  1258.         self._update()

  1259.     def setundobuffer(self, size):
  1260.         """Set or disable undobuffer.

  1261.         Argument:
  1262.         size -- an integer or None

  1263.         If size is an integer an empty undobuffer of given size is installed.
  1264.         Size gives the maximum number of turtle-actions that can be undone
  1265.         by the undo() function.
  1266.         If size is None, no undobuffer is present.

  1267.         Example (for a Turtle instance named turtle):
  1268.         >>> turtle.setundobuffer(42)
  1269.         """
  1270.         if size is None or size <= 0:
  1271.             self.undobuffer = None
  1272.         else:
  1273.             self.undobuffer = Tbuffer(size)

  1274.     def undobufferentries(self):
  1275.         """Return count of entries in the undobuffer.

  1276.         No argument.

  1277.         Example (for a Turtle instance named turtle):
  1278.         >>> while undobufferentries():
  1279.         ...     undo()
  1280.         """
  1281.         if self.undobuffer is None:
  1282.             return 0
  1283.         return self.undobuffer.nr_of_items()

  1284.     def _clear(self):
  1285.         """Delete all of pen's drawings"""
  1286.         self._fillitem = self._fillpath = None
  1287.         for item in self.items:
  1288.             self.screen._delete(item)
  1289.         self.currentLineItem = self.screen._createline()
  1290.         self.currentLine = []
  1291.         if self._drawing:
  1292.             self.currentLine.append(self._position)
  1293.         self.items = [self.currentLineItem]
  1294.         self.clearstamps()
  1295.         self.setundobuffer(self._undobuffersize)


  1296.     def clear(self):
  1297.         """Delete the turtle's drawings from the screen. Do not move turtle.

  1298.         No arguments.

  1299.         Delete the turtle's drawings from the screen. Do not move turtle.
  1300.         State and position of the turtle as well as drawings of other
  1301.         turtles are not affected.

  1302.         Examples (for a Turtle instance named turtle):
  1303.         >>> turtle.clear()
  1304.         """
  1305.         self._clear()
  1306.         self._update()

  1307.     def _update_data(self):
  1308.         self.screen._incrementudc()
  1309.         if self.screen._updatecounter != 0:
  1310.             return
  1311.         if len(self.currentLine)>1:
  1312.             self.screen._drawline(self.currentLineItem, self.currentLine,
  1313.                                   self._pencolor, self._pensize)

  1314.     def _update(self):
  1315.         """Perform a Turtle-data update.
  1316.         """
  1317.         screen = self.screen
  1318.         if screen._tracing == 0:
  1319.             return
  1320.         elif screen._tracing == 1:
  1321.             self._update_data()
  1322.             self._drawturtle()
  1323.             screen._update()                  # TurtleScreenBase
  1324.             screen._delay(screen._delayvalue) # TurtleScreenBase
  1325.         else:
  1326.             self._update_data()
  1327.             if screen._updatecounter == 0:
  1328.                 for t in screen.turtles():
  1329.                     t._drawturtle()
  1330.                 screen._update()

  1331.     def _tracer(self, flag=None, delay=None):
  1332.         """Turns turtle animation on/off and set delay for update drawings.

  1333.         Optional arguments:
  1334.         n -- nonnegative  integer
  1335.         delay -- nonnegative  integer

  1336.         If n is given, only each n-th regular screen update is really performed.
  1337.         (Can be used to accelerate the drawing of complex graphics.)
  1338.         Second arguments sets delay value (see RawTurtle.delay())

  1339.         Example (for a Turtle instance named turtle):
  1340.         >>> turtle.tracer(8, 25)
  1341.         >>> dist = 2
  1342.         >>> for i in range(200):
  1343.         ...     turtle.fd(dist)
  1344.         ...     turtle.rt(90)
  1345.         ...     dist += 2
  1346.         """
  1347.         return self.screen.tracer(flag, delay)

  1348.     def _color(self, args):
  1349.         return self.screen._color(args)

  1350.     def _colorstr(self, args):
  1351.         return self.screen._colorstr(args)

  1352.     def _cc(self, args):
  1353.         """Convert colortriples to hexstrings.
  1354.         """
  1355.         if isinstance(args, str):
  1356.             return args
  1357.         try:
  1358.             r, g, b = args
  1359.         except (TypeError, ValueError):
  1360.             raise TurtleGraphicsError("bad color arguments: %s" % str(args))
  1361.         if self.screen._colormode == 1.0:
  1362.             r, g, b = [round(255.0*x) for x in (r, g, b)]
  1363.         if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
  1364.             raise TurtleGraphicsError("bad color sequence: %s" % str(args))
  1365.         return "#%02x%02x%02x" % (r, g, b)

  1366.     def clone(self):
  1367.         """Create and return a clone of the turtle.

  1368.         No argument.

  1369.         Create and return a clone of the turtle with same position, heading
  1370.         and turtle properties.

  1371.         Example (for a Turtle instance named mick):
  1372.         mick = Turtle()
  1373.         joe = mick.clone()
  1374.         """
  1375.         screen = self.screen
  1376.         self._newLine(self._drawing)

  1377.         turtle = self.turtle
  1378.         self.screen = None
  1379.         self.turtle = None  # too make self deepcopy-able

  1380.         q = deepcopy(self)

  1381.         self.screen = screen
  1382.         self.turtle = turtle

  1383.         q.screen = screen
  1384.         q.turtle = _TurtleImage(screen, self.turtle.shapeIndex)

  1385.         screen._turtles.append(q)
  1386.         ttype = screen._shapes[self.turtle.shapeIndex]._type
  1387.         if ttype == "polygon":
  1388.             q.turtle._item = screen._createpoly()
  1389.         elif ttype == "image":
  1390.             q.turtle._item = screen._createimage(screen._shapes["blank"]._data)
  1391.         elif ttype == "compound":
  1392.             q.turtle._item = [screen._createpoly() for item in
  1393.                               screen._shapes[self.turtle.shapeIndex]._data]
  1394.         q.currentLineItem = screen._createline()
  1395.         q._update()
  1396.         return q

  1397.     def shape(self, name=None):
  1398.         """Set turtle shape to shape with given name / return current shapename.

  1399.         Optional argument:
  1400.         name -- a string, which is a valid shapename

  1401.         Set turtle shape to shape with given name or, if name is not given,
  1402.         return name of current shape.
  1403.         Shape with name must exist in the TurtleScreen's shape dictionary.
  1404.         Initially there are the following polygon shapes:
  1405.         'arrow', 'turtle', 'circle', 'square', 'triangle', 'classic'.
  1406.         To learn about how to deal with shapes see Screen-method register_shape.

  1407.         Example (for a Turtle instance named turtle):
  1408.         >>> turtle.shape()
  1409.         'arrow'
  1410.         >>> turtle.shape("turtle")
  1411.         >>> turtle.shape()
  1412.         'turtle'
  1413.         """
  1414.         if name is None:
  1415.             return self.turtle.shapeIndex
  1416.         if not name in self.screen.getshapes():
  1417.             raise TurtleGraphicsError("There is no shape named %s" % name)
  1418.         self.turtle._setshape(name)
  1419.         self._update()

  1420.     def shapesize(self, stretch_wid=None, stretch_len=None, outline=None):
  1421.         """Set/return turtle's stretchfactors/outline. Set resizemode to "user".

  1422.         Optional arguments:
  1423.            stretch_wid : positive number
  1424.            stretch_len : positive number
  1425.            outline  : positive number

  1426.         Return or set the pen's attributes x/y-stretchfactors and/or outline.
  1427.         Set resizemode to "user".
  1428.         If and only if resizemode is set to "user", the turtle will be displayed
  1429.         stretched according to its stretchfactors:
  1430.         stretch_wid is stretchfactor perpendicular to orientation
  1431.         stretch_len is stretchfactor in direction of turtles orientation.
  1432.         outline determines the width of the shapes's outline.

  1433.         Examples (for a Turtle instance named turtle):
  1434.         >>> turtle.resizemode("user")
  1435.         >>> turtle.shapesize(5, 5, 12)
  1436.         >>> turtle.shapesize(outline=8)
  1437.         """
  1438.         if stretch_wid is stretch_len is outline is None:
  1439.             stretch_wid, stretch_len = self._stretchfactor
  1440.             return stretch_wid, stretch_len, self._outlinewidth
  1441.         if stretch_wid == 0 or stretch_len == 0:
  1442.             raise TurtleGraphicsError("stretch_wid/stretch_len must not be zero")
  1443.         if stretch_wid is not None:
  1444.             if stretch_len is None:
  1445.                 stretchfactor = stretch_wid, stretch_wid
  1446.             else:
  1447.                 stretchfactor = stretch_wid, stretch_len
  1448.         elif stretch_len is not None:
  1449.             stretchfactor = self._stretchfactor[0], stretch_len
  1450.         else:
  1451.             stretchfactor = self._stretchfactor
  1452.         if outline is None:
  1453.             outline = self._outlinewidth
  1454.         self.pen(resizemode="user",
  1455.                  stretchfactor=stretchfactor, outline=outline)

  1456.     def shearfactor(self, shear=None):
  1457.         if shear is None:
  1458.             return self._shearfactor
  1459.         self.pen(resizemode="user", shearfactor=shear)

  1460.     def settiltangle(self, angle):
  1461.         tilt = -angle * self._degreesPerAU * self._angleOrient
  1462.         tilt = (tilt * math.pi / 180.0) % (2*math.pi)
  1463.         self.pen(resizemode="user", tilt=tilt)

  1464.     def tiltangle(self, angle=None):
  1465.         if angle is None:
  1466.             tilt = -self._tilt * (180.0/math.pi) * self._angleOrient
  1467.             return (tilt / self._degreesPerAU) % self._fullcircle
  1468.         else:
  1469.             self.settiltangle(angle)

  1470.     def tilt(self, angle):
  1471.         self.settiltangle(angle + self.tiltangle())

  1472.     def shapetransform(self, t11=None, t12=None, t21=None, t22=None):
  1473.         if t11 is t12 is t21 is t22 is None:
  1474.             return self._shapetrafo
  1475.         m11, m12, m21, m22 = self._shapetrafo
  1476.         if t11 is not None: m11 = t11
  1477.         if t12 is not None: m12 = t12
  1478.         if t21 is not None: m21 = t21
  1479.         if t22 is not None: m22 = t22
  1480.         if t11 * t22 - t12 * t21 == 0:
  1481.             raise TurtleGraphicsError("Bad shape transform matrix: must not be singular")
  1482.         self._shapetrafo = (m11, m12, m21, m22)
  1483.         alfa = math.atan2(-m21, m11) % (2 * math.pi)
  1484.         sa, ca = math.sin(alfa), math.cos(alfa)
  1485.         a11, a12, a21, a22 = (ca*m11 - sa*m21, ca*m12 - sa*m22,
  1486.                               sa*m11 + ca*m21, sa*m12 + ca*m22)
  1487.         self._stretchfactor = a11, a22
  1488.         self._shearfactor = a12/a22
  1489.         self._tilt = alfa
  1490.         self.pen(resizemode="user")


  1491.     def _polytrafo(self, poly):
  1492.         """Computes transformed polygon shapes from a shape
  1493.         according to current position and heading.
  1494.         """
  1495.         screen = self.screen
  1496.         p0, p1 = self._position
  1497.         e0, e1 = self._orient
  1498.         e = Vec2D(e0, e1 * screen.yscale / screen.xscale)
  1499.         e0, e1 = (1.0 / abs(e)) * e
  1500.         return [(p0+(e1*x+e0*y)/screen.xscale, p1+(-e0*x+e1*y)/screen.yscale)
  1501.                                                            for (x, y) in poly]

  1502.     def get_shapepoly(self):
  1503.         shape = self.screen._shapes[self.turtle.shapeIndex]
  1504.         if shape._type == "polygon":
  1505.             return self._getshapepoly(shape._data, shape._type == "compound")
  1506.         # else return None

  1507.     def _getshapepoly(self, polygon, compound=False):
  1508.         """Calculate transformed shape polygon according to resizemode
  1509.         and shapetransform.
  1510.         """
  1511.         if self._resizemode == "user" or compound:
  1512.             t11, t12, t21, t22 = self._shapetrafo
  1513.         elif self._resizemode == "auto":
  1514.             l = max(1, self._pensize/5.0)
  1515.             t11, t12, t21, t22 = l, 0, 0, l
  1516.         elif self._resizemode == "noresize":
  1517.             return polygon
  1518.         return tuple((t11*x + t12*y, t21*x + t22*y) for (x, y) in polygon)

  1519.     def _drawturtle(self):
  1520.         """Manages the correct rendering of the turtle with respect to
  1521.         its shape, resizemode, stretch and tilt etc."""
  1522.         screen = self.screen
  1523.         shape = screen._shapes[self.turtle.shapeIndex]
  1524.         ttype = shape._type
  1525.         titem = self.turtle._item
  1526.         if self._shown and screen._updatecounter == 0 and screen._tracing > 0:
  1527.             self._hidden_from_screen = False
  1528.             tshape = shape._data
  1529.             if ttype == "polygon":
  1530.                 if self._resizemode == "noresize": w = 1
  1531.                 elif self._resizemode == "auto": w = self._pensize
  1532.                 else: w =self._outlinewidth
  1533.                 shape = self._polytrafo(self._getshapepoly(tshape))
  1534.                 fc, oc = self._fillcolor, self._pencolor
  1535.                 screen._drawpoly(titem, shape, fill=fc, outline=oc,
  1536.                                                       width=w, top=True)
  1537.             elif ttype == "image":
  1538.                 screen._drawimage(titem, self._position, tshape)
  1539.             elif ttype == "compound":
  1540.                 for item, (poly, fc, oc) in zip(titem, tshape):
  1541.                     poly = self._polytrafo(self._getshapepoly(poly, True))
  1542.                     screen._drawpoly(item, poly, fill=self._cc(fc),
  1543.                                      outline=self._cc(oc), width=self._outlinewidth, top=True)
  1544.         else:
  1545.             if self._hidden_from_screen:
  1546.                 return
  1547.             if ttype == "polygon":
  1548.                 screen._drawpoly(titem, ((0, 0), (0, 0), (0, 0)), "", "")
  1549.             elif ttype == "image":
  1550.                 screen._drawimage(titem, self._position,
  1551.                                           screen._shapes["blank"]._data)
  1552.             elif ttype == "compound":
  1553.                 for item in titem:
  1554.                     screen._drawpoly(item, ((0, 0), (0, 0), (0, 0)), "", "")
  1555.             self._hidden_from_screen = True

  1556. ##############################  stamp stuff  ###############################

  1557.     def stamp(self):
  1558.         screen = self.screen
  1559.         shape = screen._shapes[self.turtle.shapeIndex]
  1560.         ttype = shape._type
  1561.         tshape = shape._data
  1562.         if ttype == "polygon":
  1563.             stitem = screen._createpoly()
  1564.             if self._resizemode == "noresize": w = 1
  1565.             elif self._resizemode == "auto": w = self._pensize
  1566.             else: w =self._outlinewidth
  1567.             shape = self._polytrafo(self._getshapepoly(tshape))
  1568.             fc, oc = self._fillcolor, self._pencolor
  1569.             screen._drawpoly(stitem, shape, fill=fc, outline=oc,
  1570.                                                   width=w, top=True)
  1571.         elif ttype == "image":
  1572.             stitem = screen._createimage("")
  1573.             screen._drawimage(stitem, self._position, tshape)
  1574.         elif ttype == "compound":
  1575.             stitem = []
  1576.             for element in tshape:
  1577.                 item = screen._createpoly()
  1578.                 stitem.append(item)
  1579.             stitem = tuple(stitem)
  1580.             for item, (poly, fc, oc) in zip(stitem, tshape):
  1581.                 poly = self._polytrafo(self._getshapepoly(poly, True))
  1582.                 screen._drawpoly(item, poly, fill=self._cc(fc),
  1583.                                  outline=self._cc(oc), width=self._outlinewidth, top=True)
  1584.         self.stampItems.append(stitem)
  1585.         self.undobuffer.push(("stamp", stitem))
  1586.         return stitem

  1587.     def _clearstamp(self, stampid):
  1588.         """does the work for clearstamp() and clearstamps()
  1589.         """
  1590.         if stampid in self.stampItems:
  1591.             if isinstance(stampid, tuple):
  1592.                 for subitem in stampid:
  1593.                     self.screen._delete(subitem)
  1594.             else:
  1595.                 self.screen._delete(stampid)
  1596.             self.stampItems.remove(stampid)
  1597.         # Delete stampitem from undobuffer if necessary
  1598.         # if clearstamp is called directly.
  1599.         item = ("stamp", stampid)
  1600.         buf = self.undobuffer
  1601.         if item not in buf.buffer:
  1602.             return
  1603.         index = buf.buffer.index(item)
  1604.         buf.buffer.remove(item)
  1605.         if index <= buf.ptr:
  1606.             buf.ptr = (buf.ptr - 1) % buf.bufsize
  1607.         buf.buffer.insert((buf.ptr+1)%buf.bufsize, [None])

  1608.     def clearstamp(self, stampid):
  1609.         self._clearstamp(stampid)
  1610.         self._update()

  1611.     def clearstamps(self, n=None):
  1612.         if n is None:
  1613.             toDelete = self.stampItems[:]
  1614.         elif n >= 0:
  1615.             toDelete = self.stampItems[:n]
  1616.         else:
  1617.             toDelete = self.stampItems[n:]
  1618.         for item in toDelete:
  1619.             self._clearstamp(item)
  1620.         self._update()

  1621.     def _goto(self, end):
  1622.         """Move the pen to the point end, thereby drawing a line
  1623.         if pen is down. All other methods for turtle movement depend
  1624.         on this one.
  1625.         """
  1626.         ## Version with undo-stuff
  1627.         go_modes = ( self._drawing,
  1628.                      self._pencolor,
  1629.                      self._pensize,
  1630.                      isinstance(self._fillpath, list))
  1631.         screen = self.screen
  1632.         undo_entry = ("go", self._position, end, go_modes,
  1633.                       (self.currentLineItem,
  1634.                       self.currentLine[:],
  1635.                       screen._pointlist(self.currentLineItem),
  1636.                       self.items[:])
  1637.                       )
  1638.         if self.undobuffer:
  1639.             self.undobuffer.push(undo_entry)
  1640.         start = self._position
  1641.         if self._speed and screen._tracing == 1:
  1642.             diff = (end-start)
  1643.             diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2
  1644.             nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
  1645.             delta = diff * (1.0/nhops)
  1646.             for n in range(1, nhops):
  1647.                 if n == 1:
  1648.                     top = True
  1649.                 else:
  1650.                     top = False
  1651.                 self._position = start + delta * n
  1652.                 if self._drawing:
  1653.                     screen._drawline(self.drawingLineItem,
  1654.                                      (start, self._position),
  1655.                                      self._pencolor, self._pensize, top)
  1656.                 self._update()
  1657.             if self._drawing:
  1658.                 screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
  1659.                                                fill="", width=self._pensize)
  1660.         # Turtle now at end,
  1661.         if self._drawing: # now update currentLine
  1662.             self.currentLine.append(end)
  1663.         if isinstance(self._fillpath, list):
  1664.             self._fillpath.append(end)
  1665.         ######    vererbung!!!!!!!!!!!!!!!!!!!!!!
  1666.         self._position = end
  1667.         if self._creatingPoly:
  1668.             self._poly.append(end)
  1669.         if len(self.currentLine) > 42: # 42! answer to the ultimate question
  1670.                                        # of life, the universe and everything
  1671.             self._newLine()
  1672.         self._update() #count=True)

  1673.     def _undogoto(self, entry):
  1674.         """Reverse a _goto. Used for undo()
  1675.         """
  1676.         old, new, go_modes, coodata = entry
  1677.         drawing, pc, ps, filling = go_modes
  1678.         cLI, cL, pl, items = coodata
  1679.         screen = self.screen
  1680.         if abs(self._position - new) > 0.5:
  1681.             print ("undogoto: HALLO-DA-STIMMT-WAS-NICHT!")
  1682.         # restore former situation
  1683.         self.currentLineItem = cLI
  1684.         self.currentLine = cL

  1685.         if pl == [(0, 0), (0, 0)]:
  1686.             usepc = ""
  1687.         else:
  1688.             usepc = pc
  1689.         screen._drawline(cLI, pl, fill=usepc, width=ps)

  1690.         todelete = [i for i in self.items if (i not in items) and
  1691.                                        (screen._type(i) == "line")]
  1692.         for i in todelete:
  1693.             screen._delete(i)
  1694.             self.items.remove(i)

  1695.         start = old
  1696.         if self._speed and screen._tracing == 1:
  1697.             diff = old - new
  1698.             diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2
  1699.             nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
  1700.             delta = diff * (1.0/nhops)
  1701.             for n in range(1, nhops):
  1702.                 if n == 1:
  1703.                     top = True
  1704.                 else:
  1705.                     top = False
  1706.                 self._position = new + delta * n
  1707.                 if drawing:
  1708.                     screen._drawline(self.drawingLineItem,
  1709.                                      (start, self._position),
  1710.                                      pc, ps, top)
  1711.                 self._update()
  1712.             if drawing:
  1713.                 screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
  1714.                                                fill="", width=ps)
  1715.         # Turtle now at position old,
  1716.         self._position = old

  1717.         if self._creatingPoly:
  1718.             if len(self._poly) > 0:
  1719.                 self._poly.pop()
  1720.             if self._poly == []:
  1721.                 self._creatingPoly = False
  1722.                 self._poly = None
  1723.         if filling:
  1724.             if self._fillpath == []:
  1725.                 self._fillpath = None
  1726.                 print("Unwahrscheinlich in _undogoto!")
  1727.             elif self._fillpath is not None:
  1728.                 self._fillpath.pop()
  1729.         self._update() #count=True)

  1730.     def _rotate(self, angle):
  1731.         """Turns pen clockwise by angle.
  1732.         """
  1733.         if self.undobuffer:
  1734.             self.undobuffer.push(("rot", angle, self._degreesPerAU))
  1735.         angle *= self._degreesPerAU
  1736.         neworient = self._orient.rotate(angle)
  1737.         tracing = self.screen._tracing
  1738.         if tracing == 1 and self._speed > 0:
  1739.             anglevel = 3.0 * self._speed
  1740.             steps = 1 + int(abs(angle)/anglevel)
  1741.             delta = 1.0*angle/steps
  1742.             for _ in range(steps):
  1743.                 self._orient = self._orient.rotate(delta)
  1744.                 self._update()
  1745.         self._orient = neworient
  1746.         self._update()

  1747.     def _newLine(self, usePos=True):
  1748.         if len(self.currentLine) > 1:
  1749.             self.screen._drawline(self.currentLineItem, self.currentLine,
  1750.                                       self._pencolor, self._pensize)
  1751.             self.currentLineItem = self.screen._createline()
  1752.             self.items.append(self.currentLineItem)
  1753.         else:
  1754.             self.screen._drawline(self.currentLineItem, top=True)
  1755.         self.currentLine = []
  1756.         if usePos:
  1757.             self.currentLine = [self._position]

  1758.     def filling(self):
  1759.         """Return fillstate (True if filling, False else).

  1760.         No argument.

  1761.         Example (for a Turtle instance named turtle):
  1762.         >>> turtle.begin_fill()
  1763.         >>> if turtle.filling():
  1764.         ...     turtle.pensize(5)
  1765.         ... else:
  1766.         ...     turtle.pensize(3)
  1767.         """
  1768.         return isinstance(self._fillpath, list)

  1769.     def begin_fill(self):
  1770.         if not self.filling():
  1771.             self._fillitem = self.screen._createpoly()
  1772.             self.items.append(self._fillitem)
  1773.         self._fillpath = [self._position]
  1774.         self._newLine()
  1775.         if self.undobuffer:
  1776.             self.undobuffer.push(("beginfill", self._fillitem))
  1777.         self._update()


  1778.     def end_fill(self):
  1779.         """Fill the shape drawn after the call begin_fill().

  1780.         No argument.

  1781.         Example (for a Turtle instance named turtle):
  1782.         >>> turtle.color("black", "red")
  1783.         >>> turtle.begin_fill()
  1784.         >>> turtle.circle(60)
  1785.         >>> turtle.end_fill()
  1786.         """
  1787.         if self.filling():
  1788.             if len(self._fillpath) > 2:
  1789.                 self.screen._drawpoly(self._fillitem, self._fillpath,
  1790.                                       fill=self._fillcolor)
  1791.                 if self.undobuffer:
  1792.                     self.undobuffer.push(("dofill", self._fillitem))
  1793.             self._fillitem = self._fillpath = None
  1794.             self._update()

  1795.     def dot(self, size=None, *color):
  1796.         if not color:
  1797.             if isinstance(size, (str, tuple)):
  1798.                 color = self._colorstr(size)
  1799.                 size = self._pensize + max(self._pensize, 4)
  1800.             else:
  1801.                 color = self._pencolor
  1802.                 if not size:
  1803.                     size = self._pensize + max(self._pensize, 4)
  1804.         else:
  1805.             if size is None:
  1806.                 size = self._pensize + max(self._pensize, 4)
  1807.             color = self._colorstr(color)
  1808.         if hasattr(self.screen, "_dot"):
  1809.             item = self.screen._dot(self._position, size, color)
  1810.             self.items.append(item)
  1811.             if self.undobuffer:
  1812.                 self.undobuffer.push(("dot", item))
  1813.         else:
  1814.             pen = self.pen()
  1815.             if self.undobuffer:
  1816.                 self.undobuffer.push(["seq"])
  1817.                 self.undobuffer.cumulate = True
  1818.             try:
  1819.                 if self.resizemode() == 'auto':
  1820.                     self.ht()
  1821.                 self.pendown()
  1822.                 self.pensize(size)
  1823.                 self.pencolor(color)
  1824.                 self.forward(0)
  1825.             finally:
  1826.                 self.pen(pen)
  1827.             if self.undobuffer:
  1828.                 self.undobuffer.cumulate = False

  1829.     def _write(self, txt, align, font):
  1830.         """Performs the writing for write()
  1831.         """
  1832.         item, end = self.screen._write(self._position, txt, align, font,
  1833.                                                           self._pencolor)
  1834.         self.items.append(item)
  1835.         if self.undobuffer:
  1836.             self.undobuffer.push(("wri", item))
  1837.         return end

  1838.     def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")):
  1839.         if self.undobuffer:
  1840.             self.undobuffer.push(["seq"])
  1841.             self.undobuffer.cumulate = True
  1842.         end = self._write(str(arg), align.lower(), font)
  1843.         if move:
  1844.             x, y = self.pos()
  1845.             self.setpos(end, y)
  1846.         if self.undobuffer:
  1847.             self.undobuffer.cumulate = False

  1848.     def begin_poly(self):
  1849.         """Start recording the vertices of a polygon.

  1850.         No argument.

  1851.         Start recording the vertices of a polygon. Current turtle position
  1852.         is first point of polygon.

  1853.         Example (for a Turtle instance named turtle):
  1854.         >>> turtle.begin_poly()
  1855.         """
  1856.         self._poly = [self._position]
  1857.         self._creatingPoly = True

  1858.     def end_poly(self):
  1859.         self._creatingPoly = False

  1860.     def get_poly(self):
  1861.         """Return the lastly recorded polygon.

  1862.         No argument.

  1863.         Example (for a Turtle instance named turtle):
  1864.         >>> p = turtle.get_poly()
  1865.         >>> turtle.register_shape("myFavouriteShape", p)
  1866.         """
  1867.         ## check if there is any poly?
  1868.         if self._poly is not None:
  1869.             return tuple(self._poly)

  1870.     def getscreen(self):
  1871.         return self.screen

  1872.     def getturtle(self):
  1873.         """Return the Turtleobject itself.

  1874.         No argument.

  1875.         Only reasonable use: as a function to return the 'anonymous turtle':

  1876.         Example:
  1877.         >>> pet = getturtle()
  1878.         >>> pet.fd(50)
  1879.         >>> pet
  1880.         <turtle.Turtle object at 0x0187D810>
  1881.         >>> turtles()
  1882.         [<turtle.Turtle object at 0x0187D810>]
  1883.         """
  1884.         return self

  1885.     getpen = getturtle


  1886.     ################################################################
  1887.     ### screen oriented methods recurring to methods of TurtleScreen
  1888.     ################################################################

  1889.     def _delay(self, delay=None):
  1890.         """Set delay value which determines speed of turtle animation.
  1891.         """
  1892.         return self.screen.delay(delay)

  1893.     def onclick(self, fun, btn=1, add=None):
  1894.         self.screen._onclick(self.turtle._item, fun, btn, add)
  1895.         self._update()

  1896.     def onrelease(self, fun, btn=1, add=None):
  1897.         self.screen._onrelease(self.turtle._item, fun, btn, add)
  1898.         self._update()

  1899.     def ondrag(self, fun, btn=1, add=None):
  1900.         self.screen._ondrag(self.turtle._item, fun, btn, add)


  1901.     def _undo(self, action, data):
  1902.         """Does the main part of the work for undo()
  1903.         """
  1904.         if self.undobuffer is None:
  1905.             return
  1906.         if action == "rot":
  1907.             angle, degPAU = data
  1908.             self._rotate(-angle*degPAU/self._degreesPerAU)
  1909.             dummy = self.undobuffer.pop()
  1910.         elif action == "stamp":
  1911.             stitem = data[0]
  1912.             self.clearstamp(stitem)
  1913.         elif action == "go":
  1914.             self._undogoto(data)
  1915.         elif action in ["wri", "dot"]:
  1916.             item = data[0]
  1917.             self.screen._delete(item)
  1918.             self.items.remove(item)
  1919.         elif action == "dofill":
  1920.             item = data[0]
  1921.             self.screen._drawpoly(item, ((0, 0),(0, 0),(0, 0)),
  1922.                                   fill="", outline="")
  1923.         elif action == "beginfill":
  1924.             item = data[0]
  1925.             self._fillitem = self._fillpath = None
  1926.             if item in self.items:
  1927.                 self.screen._delete(item)
  1928.                 self.items.remove(item)
  1929.         elif action == "pen":
  1930.             TPen.pen(self, data[0])
  1931.             self.undobuffer.pop()

  1932.     def undo(self):
  1933.         if self.undobuffer is None:
  1934.             return
  1935.         item = self.undobuffer.pop()
  1936.         action = item[0]
  1937.         data = item[1:]
  1938.         if action == "seq":
  1939.             while data:
  1940.                 item = data.pop()
  1941.                 self._undo(item[0], item[1:])
  1942.         else:
  1943.             self._undo(action, data)

  1944.     turtlesize = shapesize

  1945. RawPen = RawTurtle

  1946. ###  Screen - Singleton  ########################

  1947. def Screen():
  1948.     """Return the singleton screen object.
  1949.     If none exists at the moment, create a new one and return it,
  1950.     else return the existing one."""
  1951.     if Turtle._screen is None:
  1952.         Turtle._screen = _Screen()
  1953.     return Turtle._screen

  1954. class _Screen(TurtleScreen):

  1955.     _root = None
  1956.     _canvas = None
  1957.     _title = _CFG["title"]

  1958.     def __init__(self):
  1959.         if _Screen._root is None:
  1960.             _Screen._root = self._root = _Root()
  1961.             self._root.title(_Screen._title)
  1962.             self._root.ondestroy(self._destroy)
  1963.         if _Screen._canvas is None:
  1964.             width = _CFG["width"]
  1965.             height = _CFG["height"]
  1966.             canvwidth = _CFG["canvwidth"]
  1967.             canvheight = _CFG["canvheight"]
  1968.             leftright = _CFG["leftright"]
  1969.             topbottom = _CFG["topbottom"]
  1970.             self._root.setupcanvas(width, height, canvwidth, canvheight)
  1971.             _Screen._canvas = self._root._getcanvas()
  1972.             TurtleScreen.__init__(self, _Screen._canvas)
  1973.             self.setup(width, height, leftright, topbottom)

  1974.     def setup(self, width=_CFG["width"], height=_CFG["height"],
  1975.               startx=_CFG["leftright"], starty=_CFG["topbottom"]):
  1976.         if not hasattr(self._root, "set_geometry"):
  1977.             return
  1978.         sw = self._root.win_width()
  1979.         sh = self._root.win_height()
  1980.         if isinstance(width, float) and 0 <= width <= 1:
  1981.             width = sw*width
  1982.         if startx is None:
  1983.             startx = (sw - width) / 2
  1984.         if isinstance(height, float) and 0 <= height <= 1:
  1985.             height = sh*height
  1986.         if starty is None:
  1987.             starty = (sh - height) / 2
  1988.         self._root.set_geometry(width, height, startx, starty)
  1989.         self.update()

  1990.     def title(self, titlestring):
  1991.         if _Screen._root is not None:
  1992.             _Screen._root.title(titlestring)
  1993.         _Screen._title = titlestring

  1994.     def _destroy(self):
  1995.         root = self._root
  1996.         if root is _Screen._root:
  1997.             Turtle._pen = None
  1998.             Turtle._screen = None
  1999.             _Screen._root = None
  2000.             _Screen._canvas = None
  2001.         TurtleScreen._RUNNING = False
  2002.         root.destroy()

  2003.     def bye(self):
  2004.         """Shut the turtlegraphics window.

  2005.         Example (for a TurtleScreen instance named screen):
  2006.         >>> screen.bye()
  2007.         """
  2008.         self._destroy()

  2009.     def exitonclick(self):
  2010.         def exitGracefully(x, y):
  2011.             """Screen.bye() with two dummy-parameters"""
  2012.             self.bye()
  2013.         self.onclick(exitGracefully)
  2014.         if _CFG["using_IDLE"]:
  2015.             return
  2016.         try:
  2017.             mainloop()
  2018.         except AttributeError:
  2019.             exit(0)

  2020. class Turtle(RawTurtle):
  2021.     """RawTurtle auto-creating (scrolled) canvas.

  2022.     When a Turtle object is created or a function derived from some
  2023.     Turtle method is called a TurtleScreen object is automatically created.
  2024.     """
  2025.     _pen = None
  2026.     _screen = None

  2027.     def __init__(self,
  2028.                  shape=_CFG["shape"],
  2029.                  undobuffersize=_CFG["undobuffersize"],
  2030.                  visible=_CFG["visible"]):
  2031.         if Turtle._screen is None:
  2032.             Turtle._screen = Screen()
  2033.         RawTurtle.__init__(self, Turtle._screen,
  2034.                            shape=shape,
  2035.                            undobuffersize=undobuffersize,
  2036.                            visible=visible)

  2037. Pen = Turtle

  2038. def write_docstringdict(filename="turtle_docstringdict"):
  2039.     docsdict = {}

  2040.     for methodname in _tg_screen_functions:
  2041.         key = "_Screen."+methodname
  2042.         docsdict[key] = eval(key).__doc__
  2043.     for methodname in _tg_turtle_functions:
  2044.         key = "Turtle."+methodname
  2045.         docsdict[key] = eval(key).__doc__

  2046.     with open("%s.py" % filename,"w") as f:
  2047.         keys = sorted(x for x in docsdict
  2048.                       if x.split('.')[1] not in _alias_list)
  2049.         f.write('docsdict = {\n\n')
  2050.         for key in keys[:-1]:
  2051.             f.write('%s :\n' % repr(key))
  2052.             f.write('        """%s\n""",\n\n' % docsdict[key])
  2053.         key = keys[-1]
  2054.         f.write('%s :\n' % repr(key))
  2055.         f.write('        """%s\n"""\n\n' % docsdict[key])
  2056.         f.write("}\n")
  2057.         f.close()

  2058. def read_docstrings(lang):
  2059.     """Read in docstrings from lang-specific docstring dictionary.

  2060.     Transfer docstrings, translated to lang, from a dictionary-file
  2061.     to the methods of classes Screen and Turtle and - in revised form -
  2062.     to the corresponding functions.
  2063.     """
  2064.     modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
  2065.     module = __import__(modname)
  2066.     docsdict = module.docsdict
  2067.     for key in docsdict:
  2068.         try:
  2069. #            eval(key).im_func.__doc__ = docsdict[key]
  2070.             eval(key).__doc__ = docsdict[key]
  2071.         except Exception:
  2072.             print("Bad docstring-entry: %s" % key)

  2073. _LANGUAGE = _CFG["language"]

  2074. try:
  2075.     if _LANGUAGE != "english":
  2076.         read_docstrings(_LANGUAGE)
  2077. except ImportError:
  2078.     print("Cannot find docsdict for", _LANGUAGE)
  2079. except Exception:
  2080.     print ("Unknown Error when trying to import %s-docstring-dictionary" %
  2081.                                                                   _LANGUAGE)


  2082. def getmethparlist(ob):
  2083.     defText = callText = ""
  2084.     # bit of a hack for methods - turn it into a function
  2085.     # but we drop the "self" param.
  2086.     # Try and build one for Python defined functions
  2087.     args, varargs, varkw = inspect.getargs(ob.__code__)
  2088.     items2 = args[1:]
  2089.     realArgs = args[1:]
  2090.     defaults = ob.__defaults__ or []
  2091.     defaults = ["=%r" % (value,) for value in defaults]
  2092.     defaults = [""] * (len(realArgs)-len(defaults)) + defaults
  2093.     items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
  2094.     if varargs is not None:
  2095.         items1.append("*" + varargs)
  2096.         items2.append("*" + varargs)
  2097.     if varkw is not None:
  2098.         items1.append("**" + varkw)
  2099.         items2.append("**" + varkw)
  2100.     defText = ", ".join(items1)
  2101.     defText = "(%s)" % defText
  2102.     callText = ", ".join(items2)
  2103.     callText = "(%s)" % callText
  2104.     return defText, callText

  2105. def _turtle_docrevise(docstr):
  2106.     """To reduce docstrings from RawTurtle class for functions
  2107.     """
  2108.     import re
  2109.     if docstr is None:
  2110.         return None
  2111.     turtlename = _CFG["exampleturtle"]
  2112.     newdocstr = docstr.replace("%s." % turtlename,"")
  2113.     parexp = re.compile(r' \(.+ %s\):' % turtlename)
  2114.     newdocstr = parexp.sub(":", newdocstr)
  2115.     return newdocstr

  2116. def _screen_docrevise(docstr):
  2117.     """To reduce docstrings from TurtleScreen class for functions
  2118.     """
  2119.     import re
  2120.     if docstr is None:
  2121.         return None
  2122.     screenname = _CFG["examplescreen"]
  2123.     newdocstr = docstr.replace("%s." % screenname,"")
  2124.     parexp = re.compile(r' \(.+ %s\):' % screenname)
  2125.     newdocstr = parexp.sub(":", newdocstr)
  2126.     return newdocstr

  2127. ## The following mechanism makes all methods of RawTurtle and Turtle available
  2128. ## as functions. So we can enhance, change, add, delete methods to these
  2129. ## classes and do not need to change anything here.

  2130. __func_body = """\
  2131. def {name}{paramslist}:
  2132.     if {obj} is None:
  2133.         if not TurtleScreen._RUNNING:
  2134.             TurtleScreen._RUNNING = True
  2135.             raise Terminator
  2136.         {obj} = {init}
  2137.     try:
  2138.         return {obj}.{name}{argslist}
  2139.     except TK.TclError:
  2140.         if not TurtleScreen._RUNNING:
  2141.             TurtleScreen._RUNNING = True
  2142.             raise Terminator
  2143.         raise
  2144. """

  2145. def _make_global_funcs(functions, cls, obj, init, docrevise):
  2146.     for methodname in functions:
  2147.         method = getattr(cls, methodname)
  2148.         pl1, pl2 = getmethparlist(method)
  2149.         if pl1 == "":
  2150.             print(">>>>>>", pl1, pl2)
  2151.             continue
  2152.         defstr = __func_body.format(obj=obj, init=init, name=methodname,
  2153.                                     paramslist=pl1, argslist=pl2)
  2154.         exec(defstr, globals())
  2155.         globals()[methodname].__doc__ = docrevise(method.__doc__)

  2156. _make_global_funcs(_tg_screen_functions, _Screen,
  2157.                    'Turtle._screen', 'Screen()', _screen_docrevise)
  2158. _make_global_funcs(_tg_turtle_functions, Turtle,
  2159.                    'Turtle._pen', 'Turtle()', _turtle_docrevise)


  2160. done = mainloop

  2161. if __name__ == "__main__":
  2162.     def switchpen():
  2163.         if isdown():
  2164.             pu()
  2165.         else:
  2166.             pd()

  2167.     def demo1():
  2168.         """Demo of old turtle.py - module"""
  2169.         reset()
  2170.         tracer(True)
  2171.         up()
  2172.         backward(100)
  2173.         down()
  2174.         # draw 3 squares; the last filled
  2175.         width(3)
  2176.         for i in range(3):
  2177.             if i == 2:
  2178.                 begin_fill()
  2179.             for _ in range(4):
  2180.                 forward(20)
  2181.                 left(90)
  2182.             if i == 2:
  2183.                 color("maroon")
  2184.                 end_fill()
  2185.             up()
  2186.             forward(30)
  2187.             down()
  2188.         width(1)
  2189.         color("black")
  2190.         # move out of the way
  2191.         tracer(False)
  2192.         up()
  2193.         right(90)
  2194.         forward(100)
  2195.         right(90)
  2196.         forward(100)
  2197.         right(180)
  2198.         down()
  2199.         # some text
  2200.         write("startstart", 1)
  2201.         write("start", 1)
  2202.         color("red")
  2203.         # staircase
  2204.         for i in range(5):
  2205.             forward(20)
  2206.             left(90)
  2207.             forward(20)
  2208.             right(90)
  2209.         # filled staircase
  2210.         tracer(True)
  2211.         begin_fill()
  2212.         for i in range(5):
  2213.             forward(20)
  2214.             left(90)
  2215.             forward(20)
  2216.             right(90)
  2217.         end_fill()
  2218.         # more text

  2219.     def demo2():
  2220.         """Demo of some new features."""
  2221.         speed(1)
  2222.         st()
  2223.         pensize(3)
  2224.         setheading(towards(0, 0))
  2225.         radius = distance(0, 0)/2.0
  2226.         rt(90)
  2227.         for _ in range(18):
  2228.             switchpen()
  2229.             circle(radius, 10)
  2230.         write("wait a moment...")
  2231.         while undobufferentries():
  2232.             undo()
  2233.         reset()
  2234.         lt(90)
  2235.         colormode(255)
  2236.         laenge = 10
  2237.         pencolor("green")
  2238.         pensize(3)
  2239.         lt(180)
  2240.         for i in range(-2, 16):
  2241.             if i > 0:
  2242.                 begin_fill()
  2243.                 fillcolor(255-15*i, 0, 15*i)
  2244.             for _ in range(3):
  2245.                 fd(laenge)
  2246.                 lt(120)
  2247.             end_fill()
  2248.             laenge += 10
  2249.             lt(15)
  2250.             speed((speed()+1)%12)
  2251.         #end_fill()

  2252.         lt(120)
  2253.         pu()
  2254.         fd(70)
  2255.         rt(30)
  2256.         pd()
  2257.         color("red","yellow")
  2258.         speed(0)
  2259.         begin_fill()
  2260.         for _ in range(4):
  2261.             circle(50, 90)
  2262.             rt(90)
  2263.             fd(30)
  2264.             rt(90)
  2265.         end_fill()
  2266.         lt(90)
  2267.         pu()
  2268.         fd(30)
  2269.         pd()
  2270.         shape("turtle")

  2271.         tri = getturtle()
  2272.         tri.resizemode("auto")
  2273.         turtle = Turtle()
  2274.         turtle.resizemode("auto")
  2275.         turtle.shape("turtle")
  2276.         turtle.reset()
  2277.         turtle.left(90)
  2278.         turtle.speed(0)
  2279.         turtle.up()
  2280.         turtle.goto(280, 40)
  2281.         turtle.lt(30)
  2282.         turtle.down()
  2283.         turtle.speed(6)
  2284.         turtle.color("blue","orange")
  2285.         turtle.pensize(2)
  2286.         tri.speed(6)
  2287.         setheading(towards(turtle))
  2288.         count = 1
  2289.         while tri.distance(turtle) > 4:
  2290.             turtle.fd(3.5)
  2291.             turtle.lt(0.6)
  2292.             tri.setheading(tri.towards(turtle))
  2293.             tri.fd(4)
  2294.             if count % 20 == 0:
  2295.                 turtle.stamp()
  2296.                 tri.stamp()
  2297.                 switchpen()
  2298.             count += 1
  2299.         tri.write("CAUGHT! ", font=("Arial", 16, "bold"), align="right")
  2300.         tri.pencolor("black")
  2301.         tri.pencolor("red")

  2302.         def baba(xdummy, ydummy):
  2303.             clearscreen()
  2304.             bye()

  2305.         time.sleep(2)

  2306.         while undobufferentries():
  2307.             tri.undo()
  2308.             turtle.undo()
  2309.         tri.fd(50)
  2310.         tri.write("  Click me!", font = ("Courier", 12, "bold") )
  2311.         tri.onclick(baba, 1)

  2312.     demo1()
  2313.     demo2()
  2314.     exitonclick()
复制代码
最后保存应该就没问题了。(网站对帖子字数有限制,因此代码中省略了部分注释和文档,但不影响功能使用)

如果还是不行建议重装Python
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-19 15:01:07 From FishC Mobile | 显示全部楼层
安装新版本Python,建议3.8
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-20 09:33:23 | 显示全部楼层
考不好不改名 发表于 2021-2-19 14:08
你找到你Python安装的目录(默认是C:%users\33260\AppData\Local\Programs\Python);在目录下打开Lib,看 ...

加了turtle.py,还是不行,出现了新的问题,我准备安装3.8了,就是有点疑惑,后面出现的这个是为啥呢
A0210220093121.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-20 09:35:06 | 显示全部楼层

准备重装了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 03:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表