diff options
author | Ezio Melotti <ezio.melotti@gmail.com> | 2011-03-16 11:35:38 +0200 |
---|---|---|
committer | Ezio Melotti <ezio.melotti@gmail.com> | 2011-03-16 11:35:38 +0200 |
commit | a8fef3700df5400004ac88fa20c8bb4ff6f44ca3 (patch) | |
tree | 7745540e59b871e3d1b8b17757df99384cc91f68 /Lib/turtledemo | |
parent | e21d50c5c74e58bdf7173ab8d8966cfae2004728 (diff) | |
parent | 6a6e1e572574894dd211325eed26d099bde4778d (diff) | |
download | cpython-a8fef3700df5400004ac88fa20c8bb4ff6f44ca3.tar.gz |
#11565: Merge with 3.1.
Diffstat (limited to 'Lib/turtledemo')
-rw-r--r-- | Lib/turtledemo/__init__.py | 0 | ||||
-rwxr-xr-x | Lib/turtledemo/__main__.py | 266 | ||||
-rw-r--r-- | Lib/turtledemo/about_turtle.txt | 76 | ||||
-rw-r--r-- | Lib/turtledemo/about_turtledemo.txt | 13 | ||||
-rw-r--r-- | Lib/turtledemo/bytedesign.py | 162 | ||||
-rw-r--r-- | Lib/turtledemo/chaos.py | 59 | ||||
-rw-r--r-- | Lib/turtledemo/clock.py | 132 | ||||
-rw-r--r-- | Lib/turtledemo/colormixer.py | 60 | ||||
-rw-r--r-- | Lib/turtledemo/demohelp.txt | 70 | ||||
-rw-r--r-- | Lib/turtledemo/forest.py | 109 | ||||
-rw-r--r-- | Lib/turtledemo/fractalcurves.py | 138 | ||||
-rw-r--r-- | Lib/turtledemo/lindenmayer.py | 119 | ||||
-rw-r--r-- | Lib/turtledemo/minimal_hanoi.py | 76 | ||||
-rw-r--r-- | Lib/turtledemo/nim.py | 226 | ||||
-rw-r--r-- | Lib/turtledemo/paint.py | 50 | ||||
-rw-r--r-- | Lib/turtledemo/peace.py | 65 | ||||
-rw-r--r-- | Lib/turtledemo/penrose.py | 181 | ||||
-rw-r--r-- | Lib/turtledemo/planet_and_moon.py | 113 | ||||
-rw-r--r-- | Lib/turtledemo/round_dance.py | 86 | ||||
-rw-r--r-- | Lib/turtledemo/tree.py | 63 | ||||
-rw-r--r-- | Lib/turtledemo/turtle.cfg | 10 | ||||
-rw-r--r-- | Lib/turtledemo/two_canvases.py | 52 | ||||
-rw-r--r-- | Lib/turtledemo/wikipedia.py | 65 | ||||
-rw-r--r-- | Lib/turtledemo/yinyang.py | 49 |
24 files changed, 2240 insertions, 0 deletions
diff --git a/Lib/turtledemo/__init__.py b/Lib/turtledemo/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/Lib/turtledemo/__init__.py diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py new file mode 100755 index 0000000000..cbf3aeb692 --- /dev/null +++ b/Lib/turtledemo/__main__.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python3 +import sys +import os + +from tkinter import * +from idlelib.Percolator import Percolator +from idlelib.ColorDelegator import ColorDelegator +from idlelib.textView import view_file # TextViewer +from imp import reload + +import turtle +import time + +demo_dir = os.path.dirname(os.path.abspath(__file__)) + +STARTUP = 1 +READY = 2 +RUNNING = 3 +DONE = 4 +EVENTDRIVEN = 5 + +menufont = ("Arial", 12, NORMAL) +btnfont = ("Arial", 12, 'bold') +txtfont = ('Lucida Console', 8, 'normal') + +def getExampleEntries(): + return [entry[:-3] for entry in os.listdir(demo_dir) if + entry.endswith(".py") and entry[0] != '_'] + +def showDemoHelp(): + view_file(demo.root, "Help on turtleDemo", + os.path.join(demo_dir, "demohelp.txt")) + +def showAboutDemo(): + view_file(demo.root, "About turtleDemo", + os.path.join(demo_dir, "about_turtledemo.txt")) + +def showAboutTurtle(): + view_file(demo.root, "About the new turtle module.", + os.path.join(demo_dir, "about_turtle.txt")) + +class DemoWindow(object): + + def __init__(self, filename=None): #, root=None): + self.root = root = turtle._root = Tk() + root.wm_protocol("WM_DELETE_WINDOW", self._destroy) + + ################# + self.mBar = Frame(root, relief=RAISED, borderwidth=2) + self.mBar.pack(fill=X) + + self.ExamplesBtn = self.makeLoadDemoMenu() + self.OptionsBtn = self.makeHelpMenu() + self.mBar.tk_menuBar(self.ExamplesBtn, self.OptionsBtn) #, QuitBtn) + + root.title('Python turtle-graphics examples') + ################# + self.left_frame = left_frame = Frame(root) + self.text_frame = text_frame = Frame(left_frame) + self.vbar = vbar =Scrollbar(text_frame, name='vbar') + self.text = text = Text(text_frame, + name='text', padx=5, wrap='none', + width=45) + vbar['command'] = text.yview + vbar.pack(side=LEFT, fill=Y) + ##################### + self.hbar = hbar =Scrollbar(text_frame, name='hbar', orient=HORIZONTAL) + hbar['command'] = text.xview + hbar.pack(side=BOTTOM, fill=X) + ##################### + text['yscrollcommand'] = vbar.set + text.config(font=txtfont) + text.config(xscrollcommand=hbar.set) + text.pack(side=LEFT, fill=Y, expand=1) + ##################### + self.output_lbl = Label(left_frame, height= 1,text=" --- ", bg = "#ddf", + font = ("Arial", 16, 'normal')) + self.output_lbl.pack(side=BOTTOM, expand=0, fill=X) + ##################### + text_frame.pack(side=LEFT, fill=BOTH, expand=0) + left_frame.pack(side=LEFT, fill=BOTH, expand=0) + self.graph_frame = g_frame = Frame(root) + + turtle._Screen._root = g_frame + turtle._Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800) + #xturtle.Screen._canvas.pack(expand=1, fill="both") + self.screen = _s_ = turtle.Screen() +##### + turtle.TurtleScreen.__init__(_s_, _s_._canvas) +##### + self.scanvas = _s_._canvas + #xturtle.RawTurtle.canvases = [self.scanvas] + turtle.RawTurtle.screens = [_s_] + + self.scanvas.pack(side=TOP, fill=BOTH, expand=1) + + self.btn_frame = btn_frame = Frame(g_frame, height=100) + self.start_btn = Button(btn_frame, text=" START ", font=btnfont, fg = "white", + disabledforeground = "#fed", command=self.startDemo) + self.start_btn.pack(side=LEFT, fill=X, expand=1) + self.stop_btn = Button(btn_frame, text=" STOP ", font=btnfont, fg = "white", + disabledforeground = "#fed", command = self.stopIt) + self.stop_btn.pack(side=LEFT, fill=X, expand=1) + self.clear_btn = Button(btn_frame, text=" CLEAR ", font=btnfont, fg = "white", + disabledforeground = "#fed", command = self.clearCanvas) + self.clear_btn.pack(side=LEFT, fill=X, expand=1) + + self.btn_frame.pack(side=TOP, fill=BOTH, expand=0) + self.graph_frame.pack(side=TOP, fill=BOTH, expand=1) + + Percolator(text).insertfilter(ColorDelegator()) + self.dirty = False + self.exitflag = False + if filename: + self.loadfile(filename) + self.configGUI(NORMAL, DISABLED, DISABLED, DISABLED, + "Choose example from menu", "black") + self.state = STARTUP + + def _destroy(self): + self.root.destroy() + sys.exit() + + def configGUI(self, menu, start, stop, clear, txt="", color="blue"): + self.ExamplesBtn.config(state=menu) + + self.start_btn.config(state=start) + if start == NORMAL: + self.start_btn.config(bg="#d00") + else: + self.start_btn.config(bg="#fca") + + self.stop_btn.config(state=stop) + if stop == NORMAL: + self.stop_btn.config(bg="#d00") + else: + self.stop_btn.config(bg="#fca") + self.clear_btn.config(state=clear) + + self.clear_btn.config(state=clear) + if clear == NORMAL: + self.clear_btn.config(bg="#d00") + else: + self.clear_btn.config(bg="#fca") + + self.output_lbl.config(text=txt, fg=color) + + + def makeLoadDemoMenu(self): + CmdBtn = Menubutton(self.mBar, text='Examples', underline=0, font=menufont) + CmdBtn.pack(side=LEFT, padx="2m") + CmdBtn.menu = Menu(CmdBtn) + + for entry in getExampleEntries(): + def loadexample(x): + def emit(): + self.loadfile(x) + return emit + CmdBtn.menu.add_command(label=entry, underline=0, + font=menufont, command=loadexample(entry)) + + CmdBtn['menu'] = CmdBtn.menu + return CmdBtn + + def makeHelpMenu(self): + CmdBtn = Menubutton(self.mBar, text='Help', underline=0, font=menufont) + CmdBtn.pack(side=LEFT, padx='2m') + CmdBtn.menu = Menu(CmdBtn) + + CmdBtn.menu.add_command(label='About turtle.py', font=menufont, + command=showAboutTurtle) + CmdBtn.menu.add_command(label='turtleDemo - Help', font=menufont, + command=showDemoHelp) + CmdBtn.menu.add_command(label='About turtleDemo', font=menufont, + command=showAboutDemo) + + CmdBtn['menu'] = CmdBtn.menu + return CmdBtn + + def refreshCanvas(self): + if not self.dirty: return + self.screen.clear() + #self.screen.mode("standard") + self.dirty=False + + def loadfile(self, filename): + self.refreshCanvas() + modname = 'turtledemo.' + filename + __import__(modname) + self.module = sys.modules[modname] + with open(self.module.__file__, 'r') as f: + chars = f.read() + self.text.delete("1.0", "end") + self.text.insert("1.0", chars) + self.root.title(filename + " - a Python turtle graphics example") + reload(self.module) + self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED, + "Press start button", "red") + self.state = READY + + def startDemo(self): + self.refreshCanvas() + self.dirty = True + turtle.TurtleScreen._RUNNING = True + self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED, + "demo running...", "black") + self.screen.clear() + self.screen.mode("standard") + self.state = RUNNING + + try: + result = self.module.main() + if result == "EVENTLOOP": + self.state = EVENTDRIVEN + else: + self.state = DONE + except turtle.Terminator: + self.state = DONE + result = "stopped!" + if self.state == DONE: + self.configGUI(NORMAL, NORMAL, DISABLED, NORMAL, + result) + elif self.state == EVENTDRIVEN: + self.exitflag = True + self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED, + "use mouse/keys or STOP", "red") + + def clearCanvas(self): + self.refreshCanvas() + self.screen._delete("all") + self.scanvas.config(cursor="") + self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED) + + def stopIt(self): + if self.exitflag: + self.clearCanvas() + self.exitflag = False + self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED, + "STOPPED!", "red") + turtle.TurtleScreen._RUNNING = False + #print "stopIT: exitflag = True" + else: + turtle.TurtleScreen._RUNNING = False + #print "stopIt: exitflag = False" + +if __name__ == '__main__': + demo = DemoWindow() + RUN = True + while RUN: + try: + #print("ENTERING mainloop") + demo.root.mainloop() + except AttributeError: + #print("AttributeError!- WAIT A MOMENT!") + time.sleep(0.3) + print("GOING ON ..") + demo.ckearCanvas() + except TypeError: + demo.screen._delete("all") + #print("CRASH!!!- WAIT A MOMENT!") + time.sleep(0.3) + #print("GOING ON ..") + demo.clearCanvas() + except: + print("BYE!") + RUN = False diff --git a/Lib/turtledemo/about_turtle.txt b/Lib/turtledemo/about_turtle.txt new file mode 100644 index 0000000000..e4ba217c96 --- /dev/null +++ b/Lib/turtledemo/about_turtle.txt @@ -0,0 +1,76 @@ + +======================================================== + A new turtle module for Python +======================================================== + +Turtle graphics is a popular way for introducing programming to +kids. It was part of the original Logo programming language developed +by Wally Feurzig and Seymour Papert in 1966. + +Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give it +the command turtle.forward(15), and it moves (on-screen!) 15 pixels in +the direction it is facing, drawing a line as it moves. Give it the +command turtle.left(25), and it rotates in-place 25 degrees clockwise. + +By combining together these and similar commands, intricate shapes and +pictures can easily be drawn. + +----- turtle.py + +This module is an extended reimplementation of turtle.py from the +Python standard distribution up to Python 2.5. (See: http:\\www.python.org) + +It tries to keep the merits of turtle.py and to be (nearly) 100% +compatible with it. This means in the first place to enable the +learning programmer to use all the commands, classes and methods +interactively when using the module from within IDLE run with +the -n switch. + +Roughly it has the following features added: + +- Better animation of the turtle movements, especially of turning the + turtle. So the turtles can more easily be used as a visual feedback + instrument by the (beginning) programmer. + +- Different turtle shapes, gif-images as turtle shapes, user defined + and user controllable turtle shapes, among them compound + (multicolored) shapes. Turtle shapes can be stgretched and tilted, which + makes turtles zu very versatile geometrical objects. + +- Fine control over turtle movement and screen updates via delay(), + and enhanced tracer() and speed() methods. + +- Aliases for the most commonly used commands, like fd for forward etc., + following the early Logo traditions. This reduces the boring work of + typing long sequences of commands, which often occur in a natural way + when kids try to program fancy pictures on their first encounter with + turtle graphcis. + +- Turtles now have an undo()-method with configurable undo-buffer. + +- Some simple commands/methods for creating event driven programs + (mouse-, key-, timer-events). Especially useful for programming games. + +- A scrollable Canvas class. The default scrollable Canvas can be + extended interactively as needed while playing around with the turtle(s). + +- A TurtleScreen class with methods controlling background color or + background image, window and canvas size and other properties of the + TurtleScreen. + +- There is a method, setworldcoordinates(), to install a user defined + coordinate-system for the TurtleScreen. + +- The implementation uses a 2-vector class named Vec2D, derived from tuple. + This class is public, so it can be imported by the application programmer, + which makes certain types of computations very natural and compact. + +- Appearance of the TurtleScreen and the Turtles at startup/import can be + configured by means of a turtle.cfg configuration file. + The default configuration mimics the appearance of the old turtle module. + +- If configured appropriately the module reads in docstrings from a docstring + dictionary in some different language, supplied separately and replaces + the english ones by those read in. There is a utility function + write_docstringdict() to write a dictionary with the original (english) + docstrings to disc, so it can serve as a template for translations. diff --git a/Lib/turtledemo/about_turtledemo.txt b/Lib/turtledemo/about_turtledemo.txt new file mode 100644 index 0000000000..a9009bd5fb --- /dev/null +++ b/Lib/turtledemo/about_turtledemo.txt @@ -0,0 +1,13 @@ + + -------------------------------------- + About this viewer + -------------------------------------- + + Tiny demo viewer to view turtle graphics example scripts. + + Quickly and dirtyly assembled by Gregor Lingl. + June, 2006 + + For more information see: turtleDemo - Help + + Have fun! diff --git a/Lib/turtledemo/bytedesign.py b/Lib/turtledemo/bytedesign.py new file mode 100644 index 0000000000..64b1d7d5b0 --- /dev/null +++ b/Lib/turtledemo/bytedesign.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_bytedesign.py + +An example adapted from the example-suite +of PythonCard's turtle graphics. + +It's based on an article in BYTE magazine +Problem Solving with Logo: Using Turtle +Graphics to Redraw a Design +November 1982, p. 118 - 134 + +------------------------------------------- + +Due to the statement + +t.delay(0) + +in line 152, which sets the animation delay +to 0, this animation runs in "line per line" +mode as fast as possible. +""" + +import math +from turtle import Turtle, mainloop +from time import clock + +# wrapper for any additional drawing routines +# that need to know about each other +class Designer(Turtle): + + def design(self, homePos, scale): + self.up() + for i in range(5): + self.forward(64.65 * scale) + self.down() + self.wheel(self.position(), scale) + self.up() + self.backward(64.65 * scale) + self.right(72) + self.up() + self.goto(homePos) + self.right(36) + self.forward(24.5 * scale) + self.right(198) + self.down() + self.centerpiece(46 * scale, 143.4, scale) + self.getscreen().tracer(True) + + def wheel(self, initpos, scale): + self.right(54) + for i in range(4): + self.pentpiece(initpos, scale) + self.down() + self.left(36) + for i in range(5): + self.tripiece(initpos, scale) + self.left(36) + for i in range(5): + self.down() + self.right(72) + self.forward(28 * scale) + self.up() + self.backward(28 * scale) + self.left(54) + self.getscreen().update() + + def tripiece(self, initpos, scale): + oldh = self.heading() + self.down() + self.backward(2.5 * scale) + self.tripolyr(31.5 * scale, scale) + self.up() + self.goto(initpos) + self.setheading(oldh) + self.down() + self.backward(2.5 * scale) + self.tripolyl(31.5 * scale, scale) + self.up() + self.goto(initpos) + self.setheading(oldh) + self.left(72) + self.getscreen().update() + + def pentpiece(self, initpos, scale): + oldh = self.heading() + self.up() + self.forward(29 * scale) + self.down() + for i in range(5): + self.forward(18 * scale) + self.right(72) + self.pentr(18 * scale, 75, scale) + self.up() + self.goto(initpos) + self.setheading(oldh) + self.forward(29 * scale) + self.down() + for i in range(5): + self.forward(18 * scale) + self.right(72) + self.pentl(18 * scale, 75, scale) + self.up() + self.goto(initpos) + self.setheading(oldh) + self.left(72) + self.getscreen().update() + + def pentl(self, side, ang, scale): + if side < (2 * scale): return + self.forward(side) + self.left(ang) + self.pentl(side - (.38 * scale), ang, scale) + + def pentr(self, side, ang, scale): + if side < (2 * scale): return + self.forward(side) + self.right(ang) + self.pentr(side - (.38 * scale), ang, scale) + + def tripolyr(self, side, scale): + if side < (4 * scale): return + self.forward(side) + self.right(111) + self.forward(side / 1.78) + self.right(111) + self.forward(side / 1.3) + self.right(146) + self.tripolyr(side * .75, scale) + + def tripolyl(self, side, scale): + if side < (4 * scale): return + self.forward(side) + self.left(111) + self.forward(side / 1.78) + self.left(111) + self.forward(side / 1.3) + self.left(146) + self.tripolyl(side * .75, scale) + + def centerpiece(self, s, a, scale): + self.forward(s); self.left(a) + if s < (7.5 * scale): + return + self.centerpiece(s - (1.2 * scale), a, scale) + +def main(): + t = Designer() + t.speed(0) + t.hideturtle() + t.getscreen().delay(0) + t.getscreen().tracer(0) + at = clock() + t.design(t.position(), 2) + et = clock() + return "runtime: %.2f sec." % (et-at) + +if __name__ == '__main__': + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/chaos.py b/Lib/turtledemo/chaos.py new file mode 100644 index 0000000000..d4656f8914 --- /dev/null +++ b/Lib/turtledemo/chaos.py @@ -0,0 +1,59 @@ +# File: tdemo_chaos.py +# Author: Gregor Lingl +# Date: 2009-06-24 + +# A demonstration of chaos + +from turtle import * + +N = 80 + +def f(x): + return 3.9*x*(1-x) + +def g(x): + return 3.9*(x-x**2) + +def h(x): + return 3.9*x-3.9*x*x + +def jumpto(x, y): + penup(); goto(x,y) + +def line(x1, y1, x2, y2): + jumpto(x1, y1) + pendown() + goto(x2, y2) + +def coosys(): + line(-1, 0, N+1, 0) + line(0, -0.1, 0, 1.1) + +def plot(fun, start, colour): + pencolor(colour) + x = start + jumpto(0, x) + pendown() + dot(5) + for i in range(N): + x=fun(x) + goto(i+1,x) + dot(5) + +def main(): + reset() + setworldcoordinates(-1.0,-0.1, N+1, 1.1) + speed(0) + hideturtle() + coosys() + plot(f, 0.35, "blue") + plot(g, 0.35, "green") + plot(h, 0.35, "red") + # Now zoom in: + for s in range(100): + setworldcoordinates(0.5*s,-0.1, N+1, 1.1) + return "Done!" + +if __name__ == "__main__": + main() + mainloop() diff --git a/Lib/turtledemo/clock.py b/Lib/turtledemo/clock.py new file mode 100644 index 0000000000..a0d157ba49 --- /dev/null +++ b/Lib/turtledemo/clock.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# -*- coding: cp1252 -*- +""" turtle-example-suite: + + tdemo_clock.py + +Enhanced clock-program, showing date +and time + ------------------------------------ + Press STOP to exit the program! + ------------------------------------ +""" +from turtle import * +from datetime import datetime + +mode("logo") + +def jump(distanz, winkel=0): + penup() + right(winkel) + forward(distanz) + left(winkel) + pendown() + +def hand(laenge, spitze): + fd(laenge*1.15) + rt(90) + fd(spitze/2.0) + lt(120) + fd(spitze) + lt(120) + fd(spitze) + lt(120) + fd(spitze/2.0) + +def make_hand_shape(name, laenge, spitze): + reset() + jump(-laenge*0.15) + begin_poly() + hand(laenge, spitze) + end_poly() + hand_form = get_poly() + register_shape(name, hand_form) + + +def clockface(radius): + reset() + pensize(7) + for i in range(60): + jump(radius) + if i % 5 == 0: + fd(25) + jump(-radius-25) + else: + dot(3) + jump(-radius) + rt(6) + +def setup(): + global second_hand, minute_hand, hour_hand, writer + mode("logo") + make_hand_shape("second_hand", 125, 25) + make_hand_shape("minute_hand", 130, 25) + make_hand_shape("hour_hand", 90, 25) + clockface(160) + second_hand = Turtle() + second_hand.shape("second_hand") + second_hand.color("gray20", "gray80") + minute_hand = Turtle() + minute_hand.shape("minute_hand") + minute_hand.color("blue1", "red1") + hour_hand = Turtle() + hour_hand.shape("hour_hand") + hour_hand.color("blue3", "red3") + for hand in second_hand, minute_hand, hour_hand: + hand.resizemode("user") + hand.shapesize(1, 1, 3) + hand.speed(0) + ht() + writer = Turtle() + #writer.mode("logo") + writer.ht() + writer.pu() + writer.bk(85) + + +def wochentag(t): + wochentag = ["Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", "Sunday"] + return wochentag[t.weekday()] + +def datum(z): + monat = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June", + "July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."] + j = z.year + m = monat[z.month - 1] + t = z.day + return "%s %d %d" % (m, t, j) + +def tick(): + t = datetime.today() + sekunde = t.second + t.microsecond*0.000001 + minute = t.minute + sekunde/60.0 + stunde = t.hour + minute/60.0 + tracer(False) + writer.clear() + writer.home() + writer.forward(65) + writer.write(wochentag(t), + align="center", font=("Courier", 14, "bold")) + writer.back(150) + writer.write(datum(t), + align="center", font=("Courier", 14, "bold")) + writer.forward(85) + tracer(True) + second_hand.setheading(6*sekunde) + minute_hand.setheading(6*minute) + hour_hand.setheading(30*stunde) + tracer(True) + ontimer(tick, 100) + +def main(): + tracer(False) + setup() + tracer(True) + tick() + return "EVENTLOOP" + +if __name__ == "__main__": + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/colormixer.py b/Lib/turtledemo/colormixer.py new file mode 100644 index 0000000000..f5d308d443 --- /dev/null +++ b/Lib/turtledemo/colormixer.py @@ -0,0 +1,60 @@ +# colormixer + +from turtle import Screen, Turtle, mainloop +import sys +sys.setrecursionlimit(20000) # overcomes, for now, an instability of Python 3.0 + +class ColorTurtle(Turtle): + + def __init__(self, x, y): + Turtle.__init__(self) + self.shape("turtle") + self.resizemode("user") + self.shapesize(3,3,5) + self.pensize(10) + self._color = [0,0,0] + self.x = x + self._color[x] = y + self.color(self._color) + self.speed(0) + self.left(90) + self.pu() + self.goto(x,0) + self.pd() + self.sety(1) + self.pu() + self.sety(y) + self.pencolor("gray25") + self.ondrag(self.shift) + + def shift(self, x, y): + self.sety(max(0,min(y,1))) + self._color[self.x] = self.ycor() + self.fillcolor(self._color) + setbgcolor() + +def setbgcolor(): + screen.bgcolor(red.ycor(), green.ycor(), blue.ycor()) + +def main(): + global screen, red, green, blue + screen = Screen() + screen.delay(0) + screen.setworldcoordinates(-1, -0.3, 3, 1.3) + + red = ColorTurtle(0, .5) + green = ColorTurtle(1, .5) + blue = ColorTurtle(2, .5) + setbgcolor() + + writer = Turtle() + writer.ht() + writer.pu() + writer.goto(1,1.15) + writer.write("DRAG!",align="center",font=("Arial",30,("bold","italic"))) + return "EVENTLOOP" + +if __name__ == "__main__": + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/demohelp.txt b/Lib/turtledemo/demohelp.txt new file mode 100644 index 0000000000..fe83bc7601 --- /dev/null +++ b/Lib/turtledemo/demohelp.txt @@ -0,0 +1,70 @@ + + + ---------------------------------------------- + + turtleDemo - Help + + ---------------------------------------------- + + This document has two sections: + + (1) How to use the demo viewer + (2) How to add your own demos to the demo repository + + + (1) How to use the demo viewer. + + Select a demoscript from the example menu. + The (syntax coloured) source code appears in the left + source code window. IT CANNOT BE EDITED, but ONLY VIEWED! + + - Press START button to start the demo. + - Stop execution by pressing the STOP button. + - Clear screen by pressing the CLEAR button. + - Restart by pressing the START button again. + + SPECIAL demos are those which run EVENTDRIVEN. + (For example clock.py - or oldTurtleDemo.py which + in the end expects a mouse click.): + + Press START button to start the demo. + + - Until the EVENTLOOP is entered everything works + as in an ordinary demo script. + + - When the EVENTLOOP is entered, you control the + application by using the mouse and/or keys (or it's + controlled by some timer events) + To stop it you can and must press the STOP button. + + While the EVENTLOOP is running, the examples menu is disabled. + + - Only after having pressed the STOP button, you may + restart it or choose another example script. + + * * * * * * * * + In some rare situations there may occur interferences/conflicts + between events concerning the demo script and those concerning the + demo-viewer. (They run in the same process.) Strange behaviour may be + the consequence and in the worst case you must close and restart the + viewer. + * * * * * * * * + + + (2) How to add your own demos to the demo repository + + - place: same directory as turtledemo/__main__.py + + - requirements on source code: + code must contain a main() function which will + be executed by the viewer (see provided example scripts) + main() may return a string which will be displayed + in the Label below the source code window (when execution + has finished.) + + !! For programs, which are EVENT DRIVEN, main must return + !! the string "EVENTLOOP". This informs the viewer, that the + !! script is still running and must be stopped by the user! + + + diff --git a/Lib/turtledemo/forest.py b/Lib/turtledemo/forest.py new file mode 100644 index 0000000000..a837d844c9 --- /dev/null +++ b/Lib/turtledemo/forest.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +""" turtlegraphics-example-suite: + + tdemo_forest.py + +Displays a 'forest' of 3 'breadth-first-trees' +similar to the one from example tree. +For further remarks see xtx_tree.py + +This example is a 'breadth-first'-rewrite of +a Logo program written by Erich Neuwirth. See: +http://homepage.univie.ac.at/erich.neuwirth/ +""" +from turtle import Turtle, colormode, tracer, mainloop +from random import randrange +from time import clock + +def symRandom(n): + return randrange(-n,n+1) + +def randomize( branchlist, angledist, sizedist ): + return [ (angle+symRandom(angledist), + sizefactor*1.01**symRandom(sizedist)) + for angle, sizefactor in branchlist ] + +def randomfd( t, distance, parts, angledist ): + for i in range(parts): + t.left(symRandom(angledist)) + t.forward( (1.0 * distance)/parts ) + +def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5): + # benutzt Liste von turtles und Liste von Zweiglisten, + # fuer jede turtle eine! + if level > 0: + lst = [] + brs = [] + for t, branchlist in list(zip(tlist,branchlists)): + t.pensize( size * widthfactor ) + t.pencolor( 255 - (180 - 11 * level + symRandom(15)), + 180 - 11 * level + symRandom(15), + 0 ) + t.pendown() + randomfd(t, size, level, angledist ) + yield 1 + for angle, sizefactor in branchlist: + t.left(angle) + lst.append(t.clone()) + brs.append(randomize(branchlist, angledist, sizedist)) + t.right(angle) + for x in tree(lst, size*sizefactor, level-1, widthfactor, brs, + angledist, sizedist): + yield None + + +def start(t,x,y): + colormode(255) + t.reset() + t.speed(0) + t.hideturtle() + t.left(90) + t.penup() + t.setpos(x,y) + t.pendown() + +def doit1(level, pen): + pen.hideturtle() + start(pen, 20, -208) + t = tree( [pen], 80, level, 0.1, [[ (45,0.69), (0,0.65), (-45,0.71) ]] ) + return t + +def doit2(level, pen): + pen.hideturtle() + start(pen, -135, -130) + t = tree( [pen], 120, level, 0.1, [[ (45,0.69), (-45,0.71) ]] ) + return t + +def doit3(level, pen): + pen.hideturtle() + start(pen, 190, -90) + t = tree( [pen], 100, level, 0.1, [[ (45,0.7), (0,0.72), (-45,0.65) ]] ) + return t + +# Hier 3 Baumgeneratoren: +def main(): + p = Turtle() + p.ht() + tracer(75,0) + u = doit1(6, Turtle(undobuffersize=1)) + s = doit2(7, Turtle(undobuffersize=1)) + t = doit3(5, Turtle(undobuffersize=1)) + a = clock() + while True: + done = 0 + for b in u,s,t: + try: + b.__next__() + except: + done += 1 + if done == 3: + break + + tracer(1,10) + b = clock() + return "runtime: %.2f sec." % (b-a) + +if __name__ == '__main__': + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/fractalcurves.py b/Lib/turtledemo/fractalcurves.py new file mode 100644 index 0000000000..c49f8b88ea --- /dev/null +++ b/Lib/turtledemo/fractalcurves.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_fractalCurves.py + +This program draws two fractal-curve-designs: +(1) A hilbert curve (in a box) +(2) A combination of Koch-curves. + +The CurvesTurtle class and the fractal-curve- +methods are taken from the PythonCard example +scripts for turtle-graphics. +""" +from turtle import * +from time import sleep, clock + +class CurvesTurtle(Pen): + # example derived from + # Turtle Geometry: The Computer as a Medium for Exploring Mathematics + # by Harold Abelson and Andrea diSessa + # p. 96-98 + def hilbert(self, size, level, parity): + if level == 0: + return + # rotate and draw first subcurve with opposite parity to big curve + self.left(parity * 90) + self.hilbert(size, level - 1, -parity) + # interface to and draw second subcurve with same parity as big curve + self.forward(size) + self.right(parity * 90) + self.hilbert(size, level - 1, parity) + # third subcurve + self.forward(size) + self.hilbert(size, level - 1, parity) + # fourth subcurve + self.right(parity * 90) + self.forward(size) + self.hilbert(size, level - 1, -parity) + # a final turn is needed to make the turtle + # end up facing outward from the large square + self.left(parity * 90) + + # Visual Modeling with Logo: A Structural Approach to Seeing + # by James Clayson + # Koch curve, after Helge von Koch who introduced this geometric figure in 1904 + # p. 146 + def fractalgon(self, n, rad, lev, dir): + import math + + # if dir = 1 turn outward + # if dir = -1 turn inward + edge = 2 * rad * math.sin(math.pi / n) + self.pu() + self.fd(rad) + self.pd() + self.rt(180 - (90 * (n - 2) / n)) + for i in range(n): + self.fractal(edge, lev, dir) + self.rt(360 / n) + self.lt(180 - (90 * (n - 2) / n)) + self.pu() + self.bk(rad) + self.pd() + + # p. 146 + def fractal(self, dist, depth, dir): + if depth < 1: + self.fd(dist) + return + self.fractal(dist / 3, depth - 1, dir) + self.lt(60 * dir) + self.fractal(dist / 3, depth - 1, dir) + self.rt(120 * dir) + self.fractal(dist / 3, depth - 1, dir) + self.lt(60 * dir) + self.fractal(dist / 3, depth - 1, dir) + +def main(): + ft = CurvesTurtle() + + ft.reset() + ft.speed(0) + ft.ht() + ft.getscreen().tracer(1,0) + ft.pu() + + size = 6 + ft.setpos(-33*size, -32*size) + ft.pd() + + ta=clock() + ft.fillcolor("red") + ft.begin_fill() + ft.fd(size) + + ft.hilbert(size, 6, 1) + + # frame + ft.fd(size) + for i in range(3): + ft.lt(90) + ft.fd(size*(64+i%2)) + ft.pu() + for i in range(2): + ft.fd(size) + ft.rt(90) + ft.pd() + for i in range(4): + ft.fd(size*(66+i%2)) + ft.rt(90) + ft.end_fill() + tb=clock() + res = "Hilbert: %.2fsec. " % (tb-ta) + + sleep(3) + + ft.reset() + ft.speed(0) + ft.ht() + ft.getscreen().tracer(1,0) + + ta=clock() + ft.color("black", "blue") + ft.begin_fill() + ft.fractalgon(3, 250, 4, 1) + ft.end_fill() + ft.begin_fill() + ft.color("red") + ft.fractalgon(3, 200, 4, -1) + ft.end_fill() + tb=clock() + res += "Koch: %.2fsec." % (tb-ta) + return res + +if __name__ == '__main__': + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/lindenmayer.py b/Lib/turtledemo/lindenmayer.py new file mode 100644 index 0000000000..3925f25da6 --- /dev/null +++ b/Lib/turtledemo/lindenmayer.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + xtx_lindenmayer_indian.py + +Each morning women in Tamil Nadu, in southern +India, place designs, created by using rice +flour and known as kolam on the thresholds of +their homes. + +These can be described by Lindenmayer systems, +which can easily be implemented with turtle +graphics and Python. + +Two examples are shown here: +(1) the snake kolam +(2) anklets of Krishna + +Taken from Marcia Ascher: Mathematics +Elsewhere, An Exploration of Ideas Across +Cultures + +""" +################################ +# Mini Lindenmayer tool +############################### + +from turtle import * + +def replace( seq, replacementRules, n ): + for i in range(n): + newseq = "" + for element in seq: + newseq = newseq + replacementRules.get(element,element) + seq = newseq + return seq + +def draw( commands, rules ): + for b in commands: + try: + rules[b]() + except TypeError: + try: + draw(rules[b], rules) + except: + pass + + +def main(): + ################################ + # Example 1: Snake kolam + ################################ + + + def r(): + right(45) + + def l(): + left(45) + + def f(): + forward(7.5) + + snake_rules = {"-":r, "+":l, "f":f, "b":"f+f+f--f--f+f+f"} + snake_replacementRules = {"b": "b+f+b--f--b+f+b"} + snake_start = "b--f--b--f" + + drawing = replace(snake_start, snake_replacementRules, 3) + + reset() + speed(3) + tracer(1,0) + ht() + up() + backward(195) + down() + draw(drawing, snake_rules) + + from time import sleep + sleep(3) + + ################################ + # Example 2: Anklets of Krishna + ################################ + + def A(): + color("red") + circle(10,90) + + def B(): + from math import sqrt + color("black") + l = 5/sqrt(2) + forward(l) + circle(l, 270) + forward(l) + + def F(): + color("green") + forward(10) + + krishna_rules = {"a":A, "b":B, "f":F} + krishna_replacementRules = {"a" : "afbfa", "b" : "afbfbfbfa" } + krishna_start = "fbfbfbfb" + + reset() + speed(0) + tracer(3,0) + ht() + left(45) + drawing = replace(krishna_start, krishna_replacementRules, 3) + draw(drawing, krishna_rules) + tracer(1) + return "Done!" + +if __name__=='__main__': + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/minimal_hanoi.py b/Lib/turtledemo/minimal_hanoi.py new file mode 100644 index 0000000000..cfb78dcac1 --- /dev/null +++ b/Lib/turtledemo/minimal_hanoi.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_minimal_hanoi.py + +A minimal 'Towers of Hanoi' animation: +A tower of 6 discs is transferred from the +left to the right peg. + +An imho quite elegant and concise +implementation using a tower class, which +is derived from the built-in type list. + +Discs are turtles with shape "square", but +stretched to rectangles by shapesize() + --------------------------------------- + To exit press STOP button + --------------------------------------- +""" +from turtle import * + +class Disc(Turtle): + def __init__(self, n): + Turtle.__init__(self, shape="square", visible=False) + self.pu() + self.shapesize(1.5, n*1.5, 2) # square-->rectangle + self.fillcolor(n/6., 0, 1-n/6.) + self.st() + +class Tower(list): + "Hanoi tower, a subclass of built-in type list" + def __init__(self, x): + "create an empty tower. x is x-position of peg" + self.x = x + def push(self, d): + d.setx(self.x) + d.sety(-150+34*len(self)) + self.append(d) + def pop(self): + d = list.pop(self) + d.sety(150) + return d + +def hanoi(n, from_, with_, to_): + if n > 0: + hanoi(n-1, from_, to_, with_) + to_.push(from_.pop()) + hanoi(n-1, with_, from_, to_) + +def play(): + onkey(None,"space") + clear() + hanoi(6, t1, t2, t3) + write("press STOP button to exit", + align="center", font=("Courier", 16, "bold")) + +def main(): + global t1, t2, t3 + ht(); penup(); goto(0, -225) # writer turtle + t1 = Tower(-250) + t2 = Tower(0) + t3 = Tower(250) + # make tower of 6 discs + for i in range(6,0,-1): + t1.push(Disc(i)) + # prepare spartanic user interface ;-) + write("press spacebar to start game", + align="center", font=("Courier", 16, "bold")) + onkey(play, "space") + listen() + return "EVENTLOOP" + +if __name__=="__main__": + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/nim.py b/Lib/turtledemo/nim.py new file mode 100644 index 0000000000..792ba51534 --- /dev/null +++ b/Lib/turtledemo/nim.py @@ -0,0 +1,226 @@ +""" turtle-example-suite: + + tdemo_nim.py + +Play nim against the computer. The player +who takes the last stick is the winner. + +Implements the model-view-controller +design pattern. +""" + + +import turtle +import random +import time + +SCREENWIDTH = 640 +SCREENHEIGHT = 480 + +MINSTICKS = 7 +MAXSTICKS = 31 + +HUNIT = SCREENHEIGHT // 12 +WUNIT = SCREENWIDTH // ((MAXSTICKS // 5) * 11 + (MAXSTICKS % 5) * 2) + +SCOLOR = (63, 63, 31) +HCOLOR = (255, 204, 204) +COLOR = (204, 204, 255) + +def randomrow(): + return random.randint(MINSTICKS, MAXSTICKS) + +def computerzug(state): + xored = state[0] ^ state[1] ^ state[2] + if xored == 0: + return randommove(state) + for z in range(3): + s = state[z] ^ xored + if s <= state[z]: + move = (z, s) + return move + +def randommove(state): + m = max(state) + while True: + z = random.randint(0,2) + if state[z] > (m > 1): + break + rand = random.randint(m > 1, state[z]-1) + return z, rand + + +class NimModel(object): + def __init__(self, game): + self.game = game + + def setup(self): + if self.game.state not in [Nim.CREATED, Nim.OVER]: + return + self.sticks = [randomrow(), randomrow(), randomrow()] + self.player = 0 + self.winner = None + self.game.view.setup() + self.game.state = Nim.RUNNING + + def move(self, row, col): + maxspalte = self.sticks[row] + self.sticks[row] = col + self.game.view.notify_move(row, col, maxspalte, self.player) + if self.game_over(): + self.game.state = Nim.OVER + self.winner = self.player + self.game.view.notify_over() + elif self.player == 0: + self.player = 1 + row, col = computerzug(self.sticks) + self.move(row, col) + self.player = 0 + + def game_over(self): + return self.sticks == [0, 0, 0] + + def notify_move(self, row, col): + if self.sticks[row] <= col: + return + self.move(row, col) + + +class Stick(turtle.Turtle): + def __init__(self, row, col, game): + turtle.Turtle.__init__(self, visible=False) + self.row = row + self.col = col + self.game = game + x, y = self.coords(row, col) + self.shape("square") + self.shapesize(HUNIT/10.0, WUNIT/20.0) + self.speed(0) + self.pu() + self.goto(x,y) + self.color("white") + self.showturtle() + + def coords(self, row, col): + packet, remainder = divmod(col, 5) + x = (3 + 11 * packet + 2 * remainder) * WUNIT + y = (2 + 3 * row) * HUNIT + return x - SCREENWIDTH // 2 + WUNIT // 2, SCREENHEIGHT // 2 - y - HUNIT // 2 + + def makemove(self, x, y): + if self.game.state != Nim.RUNNING: + return + self.game.controller.notify_move(self.row, self.col) + + +class NimView(object): + def __init__(self, game): + self.game = game + self.screen = game.screen + self.model = game.model + self.screen.colormode(255) + self.screen.tracer(False) + self.screen.bgcolor((240, 240, 255)) + self.writer = turtle.Turtle(visible=False) + self.writer.pu() + self.writer.speed(0) + self.sticks = {} + for row in range(3): + for col in range(MAXSTICKS): + self.sticks[(row, col)] = Stick(row, col, game) + self.display("... a moment please ...") + self.screen.tracer(True) + + def display(self, msg1, msg2=None): + self.screen.tracer(False) + self.writer.clear() + if msg2 is not None: + self.writer.goto(0, - SCREENHEIGHT // 2 + 48) + self.writer.pencolor("red") + self.writer.write(msg2, align="center", font=("Courier",18,"bold")) + self.writer.goto(0, - SCREENHEIGHT // 2 + 20) + self.writer.pencolor("black") + self.writer.write(msg1, align="center", font=("Courier",14,"bold")) + self.screen.tracer(True) + + + def setup(self): + self.screen.tracer(False) + for row in range(3): + for col in range(self.model.sticks[row]): + self.sticks[(row, col)].color(SCOLOR) + for row in range(3): + for col in range(self.model.sticks[row], MAXSTICKS): + self.sticks[(row, col)].color("white") + self.display("Your turn! Click leftmost stick to remove.") + self.screen.tracer(True) + + def notify_move(self, row, col, maxspalte, player): + if player == 0: + farbe = HCOLOR + for s in range(col, maxspalte): + self.sticks[(row, s)].color(farbe) + else: + self.display(" ... thinking ... ") + time.sleep(0.5) + self.display(" ... thinking ... aaah ...") + farbe = COLOR + for s in range(maxspalte-1, col-1, -1): + time.sleep(0.2) + self.sticks[(row, s)].color(farbe) + self.display("Your turn! Click leftmost stick to remove.") + + def notify_over(self): + if self.game.model.winner == 0: + msg2 = "Congrats. You're the winner!!!" + else: + msg2 = "Sorry, the computer is the winner." + self.display("To play again press space bar. To leave press ESC.", msg2) + + def clear(self): + if self.game.state == Nim.OVER: + self.screen.clear() + +class NimController(object): + + def __init__(self, game): + self.game = game + self.sticks = game.view.sticks + self.BUSY = False + for stick in self.sticks.values(): + stick.onclick(stick.makemove) + self.game.screen.onkey(self.game.model.setup, "space") + self.game.screen.onkey(self.game.view.clear, "Escape") + self.game.view.display("Press space bar to start game") + self.game.screen.listen() + + def notify_move(self, row, col): + if self.BUSY: + return + self.BUSY = True + self.game.model.notify_move(row, col) + self.BUSY = False + +class Nim(object): + CREATED = 0 + RUNNING = 1 + OVER = 2 + def __init__(self, screen): + self.state = Nim.CREATED + self.screen = screen + self.model = NimModel(self) + self.view = NimView(self) + self.controller = NimController(self) + + +mainscreen = turtle.Screen() +mainscreen.mode("standard") +mainscreen.setup(SCREENWIDTH, SCREENHEIGHT) + +def main(): + nim = Nim(mainscreen) + return "EVENTLOOP!" + +if __name__ == "__main__": + main() + turtle.mainloop() diff --git a/Lib/turtledemo/paint.py b/Lib/turtledemo/paint.py new file mode 100644 index 0000000000..68058ab6ac --- /dev/null +++ b/Lib/turtledemo/paint.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_paint.py + +A simple eventdriven paint program + +- use left mouse button to move turtle +- middle mouse button to change color +- right mouse button do turn filling on/off + ------------------------------------------- + Play around by clicking into the canvas + using all three mouse buttons. + ------------------------------------------- + To exit press STOP button + ------------------------------------------- +""" +from turtle import * + +def switchupdown(x=0, y=0): + if pen()["pendown"]: + end_fill() + up() + else: + down() + begin_fill() + +def changecolor(x=0, y=0): + global colors + colors = colors[1:]+colors[:1] + color(colors[0]) + +def main(): + global colors + shape("circle") + resizemode("user") + shapesize(.5) + width(3) + colors=["red", "green", "blue", "yellow"] + color(colors[0]) + switchupdown() + onscreenclick(goto,1) + onscreenclick(changecolor,2) + onscreenclick(switchupdown,3) + return "EVENTLOOP" + +if __name__ == "__main__": + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/peace.py b/Lib/turtledemo/peace.py new file mode 100644 index 0000000000..63cf7cc2e1 --- /dev/null +++ b/Lib/turtledemo/peace.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_peace.py + +A very simple drawing suitable as a beginner's +programming example. + +Uses only commands, which are also available in +old turtle.py. + +Intentionally no variables are used except for the +colorloop: +""" + +from turtle import * + +def main(): + peacecolors = ("red3", "orange", "yellow", + "seagreen4", "orchid4", + "royalblue1", "dodgerblue4") + + reset() + s = Screen() + up() + goto(-320,-195) + width(70) + + for pcolor in peacecolors: + color(pcolor) + down() + forward(640) + up() + backward(640) + left(90) + forward(66) + right(90) + + width(25) + color("white") + goto(0,-170) + down() + + circle(170) + left(90) + forward(340) + up() + left(180) + forward(170) + right(45) + down() + forward(170) + up() + backward(170) + left(90) + down() + forward(170) + up() + + goto(0,300) # vanish if hideturtle() is not available ;-) + return "Done!!" + +if __name__ == "__main__": + main() + mainloop() diff --git a/Lib/turtledemo/penrose.py b/Lib/turtledemo/penrose.py new file mode 100644 index 0000000000..f73c864b7b --- /dev/null +++ b/Lib/turtledemo/penrose.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +""" xturtle-example-suite: + + xtx_kites_and_darts.py + +Constructs two aperiodic penrose-tilings, +consisting of kites and darts, by the method +of inflation in six steps. + +Starting points are the patterns "sun" +consisting of five kites and "star" +consisting of five darts. + +For more information see: + http://en.wikipedia.org/wiki/Penrose_tiling + ------------------------------------------- +""" +from turtle import * +from math import cos, pi +from time import clock, sleep + +f = (5**0.5-1)/2.0 # (sqrt(5)-1)/2 -- golden ratio +d = 2 * cos(3*pi/10) + +def kite(l): + fl = f * l + lt(36) + fd(l) + rt(108) + fd(fl) + rt(36) + fd(fl) + rt(108) + fd(l) + rt(144) + +def dart(l): + fl = f * l + lt(36) + fd(l) + rt(144) + fd(fl) + lt(36) + fd(fl) + rt(144) + fd(l) + rt(144) + +def inflatekite(l, n): + if n == 0: + px, py = pos() + h, x, y = int(heading()), round(px,3), round(py,3) + tiledict[(h,x,y)] = True + return + fl = f * l + lt(36) + inflatedart(fl, n-1) + fd(l) + rt(144) + inflatekite(fl, n-1) + lt(18) + fd(l*d) + rt(162) + inflatekite(fl, n-1) + lt(36) + fd(l) + rt(180) + inflatedart(fl, n-1) + lt(36) + +def inflatedart(l, n): + if n == 0: + px, py = pos() + h, x, y = int(heading()), round(px,3), round(py,3) + tiledict[(h,x,y)] = False + return + fl = f * l + inflatekite(fl, n-1) + lt(36) + fd(l) + rt(180) + inflatedart(fl, n-1) + lt(54) + fd(l*d) + rt(126) + inflatedart(fl, n-1) + fd(l) + rt(144) + +def draw(l, n, th=2): + clear() + l = l * f**n + shapesize(l/100.0, l/100.0, th) + for k in tiledict: + h, x, y = k + setpos(x, y) + setheading(h) + if tiledict[k]: + shape("kite") + color("black", (0, 0.75, 0)) + else: + shape("dart") + color("black", (0.75, 0, 0)) + stamp() + +def sun(l, n): + for i in range(5): + inflatekite(l, n) + lt(72) + +def star(l,n): + for i in range(5): + inflatedart(l, n) + lt(72) + +def makeshapes(): + tracer(0) + begin_poly() + kite(100) + end_poly() + register_shape("kite", get_poly()) + begin_poly() + dart(100) + end_poly() + register_shape("dart", get_poly()) + tracer(1) + +def start(): + reset() + ht() + pu() + makeshapes() + resizemode("user") + +def test(l=200, n=4, fun=sun, startpos=(0,0), th=2): + global tiledict + goto(startpos) + setheading(0) + tiledict = {} + a = clock() + tracer(0) + fun(l, n) + b = clock() + draw(l, n, th) + tracer(1) + c = clock() + print("Calculation: %7.4f s" % (b - a)) + print("Drawing: %7.4f s" % (c - b)) + print("Together: %7.4f s" % (c - a)) + nk = len([x for x in tiledict if tiledict[x]]) + nd = len([x for x in tiledict if not tiledict[x]]) + print("%d kites and %d darts = %d pieces." % (nk, nd, nk+nd)) + +def demo(fun=sun): + start() + for i in range(8): + a = clock() + test(300, i, fun) + b = clock() + t = b - a + if t < 2: + sleep(2 - t) + +def main(): + #title("Penrose-tiling with kites and darts.") + mode("logo") + bgcolor(0.3, 0.3, 0) + demo(sun) + sleep(2) + demo(star) + pencolor("black") + goto(0,-200) + pencolor(0.7,0.7,1) + write("Please wait...", + align="center", font=('Arial Black', 36, 'bold')) + test(600, 8, startpos=(70, 117)) + return "Done" + +if __name__ == "__main__": + msg = main() + mainloop() diff --git a/Lib/turtledemo/planet_and_moon.py b/Lib/turtledemo/planet_and_moon.py new file mode 100644 index 0000000000..14c4bbccc4 --- /dev/null +++ b/Lib/turtledemo/planet_and_moon.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_planets_and_moon.py + +Gravitational system simulation using the +approximation method from Feynman-lectures, +p.9-8, using turtlegraphics. + +Example: heavy central body, light planet, +very light moon! +Planet has a circular orbit, moon a stable +orbit around the planet. + +You can hold the movement temporarily by pressing +the left mouse button with mouse over the +scrollbar of the canvas. + +""" +from turtle import Shape, Turtle, mainloop, Vec2D as Vec +from time import sleep + +G = 8 + +class GravSys(object): + def __init__(self): + self.planets = [] + self.t = 0 + self.dt = 0.01 + def init(self): + for p in self.planets: + p.init() + def start(self): + for i in range(10000): + self.t += self.dt + for p in self.planets: + p.step() + +class Star(Turtle): + def __init__(self, m, x, v, gravSys, shape): + Turtle.__init__(self, shape=shape) + self.penup() + self.m = m + self.setpos(x) + self.v = v + gravSys.planets.append(self) + self.gravSys = gravSys + self.resizemode("user") + self.pendown() + def init(self): + dt = self.gravSys.dt + self.a = self.acc() + self.v = self.v + 0.5*dt*self.a + def acc(self): + a = Vec(0,0) + for planet in self.gravSys.planets: + if planet != self: + v = planet.pos()-self.pos() + a += (G*planet.m/abs(v)**3)*v + return a + def step(self): + dt = self.gravSys.dt + self.setpos(self.pos() + dt*self.v) + if self.gravSys.planets.index(self) != 0: + self.setheading(self.towards(self.gravSys.planets[0])) + self.a = self.acc() + self.v = self.v + dt*self.a + +## create compound yellow/blue turtleshape for planets + +def main(): + s = Turtle() + s.reset() + s.getscreen().tracer(0,0) + s.ht() + s.pu() + s.fd(6) + s.lt(90) + s.begin_poly() + s.circle(6, 180) + s.end_poly() + m1 = s.get_poly() + s.begin_poly() + s.circle(6,180) + s.end_poly() + m2 = s.get_poly() + + planetshape = Shape("compound") + planetshape.addcomponent(m1,"orange") + planetshape.addcomponent(m2,"blue") + s.getscreen().register_shape("planet", planetshape) + s.getscreen().tracer(1,0) + + ## setup gravitational system + gs = GravSys() + sun = Star(1000000, Vec(0,0), Vec(0,-2.5), gs, "circle") + sun.color("yellow") + sun.shapesize(1.8) + sun.pu() + earth = Star(12500, Vec(210,0), Vec(0,195), gs, "planet") + earth.pencolor("green") + earth.shapesize(0.8) + moon = Star(1, Vec(220,0), Vec(0,295), gs, "planet") + moon.pencolor("blue") + moon.shapesize(0.5) + gs.init() + gs.start() + return "Done!" + +if __name__ == '__main__': + msg = main() + print(msg) + #mainloop() diff --git a/Lib/turtledemo/round_dance.py b/Lib/turtledemo/round_dance.py new file mode 100644 index 0000000000..10383614c6 --- /dev/null +++ b/Lib/turtledemo/round_dance.py @@ -0,0 +1,86 @@ +""" turtle-example-suite: + + tdemo_round_dance.py + +(Needs version 1.1 of the turtle module that +comes with Python 3.1) + +Dancing turtles have a compound shape +consisting of a series of triangles of +decreasing size. + +Turtles march along a circle while rotating +pairwise in opposite direction, with one +exception. Does that breaking of symmetry +enhance the attractiveness of the example? + +Press any key to stop the animation. + +Technically: demonstrates use of compound +shapes, transformation of shapes as well as +cloning turtles. The animation is +controlled through update(). +""" + +from turtle import * + +def stop(): + global running + running = False + +def main(): + global running + clearscreen() + bgcolor("gray10") + tracer(False) + shape("triangle") + f = 0.793402 + phi = 9.064678 + s = 5 + c = 1 + # create compound shape + sh = Shape("compound") + for i in range(10): + shapesize(s) + p =get_shapepoly() + s *= f + c *= f + tilt(-phi) + sh.addcomponent(p, (c, 0.25, 1-c), "black") + register_shape("multitri", sh) + # create dancers + shapesize(1) + shape("multitri") + pu() + setpos(0, -200) + dancers = [] + for i in range(180): + fd(7) + tilt(-4) + lt(2) + update() + if i % 12 == 0: + dancers.append(clone()) + home() + # dance + running = True + onkeypress(stop) + listen() + cs = 1 + while running: + ta = -4 + for dancer in dancers: + dancer.fd(7) + dancer.lt(2) + dancer.tilt(ta) + ta = -4 if ta > 0 else 2 + if cs < 180: + right(4) + shapesize(cs) + cs *= 1.005 + update() + return "DONE!" + +if __name__=='__main__': + print(main()) + mainloop() diff --git a/Lib/turtledemo/tree.py b/Lib/turtledemo/tree.py new file mode 100644 index 0000000000..9c0b1f7bb4 --- /dev/null +++ b/Lib/turtledemo/tree.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_tree.py + +Displays a 'breadth-first-tree' - in contrast +to the classical Logo tree drawing programs, +which use a depth-first-algorithm. + +Uses: +(1) a tree-generator, where the drawing is +quasi the side-effect, whereas the generator +always yields None. +(2) Turtle-cloning: At each branching point the +current pen is cloned. So in the end there +are 1024 turtles. +""" +from turtle import Turtle, mainloop +from time import clock + +def tree(plist, l, a, f): + """ plist is list of pens + l is length of branch + a is half of the angle between 2 branches + f is factor by which branch is shortened + from level to level.""" + if l > 3: + lst = [] + for p in plist: + p.forward(l) + q = p.clone() + p.left(a) + q.right(a) + lst.append(p) + lst.append(q) + for x in tree(lst, l*f, a, f): + yield None + +def maketree(): + p = Turtle() + p.setundobuffer(None) + p.hideturtle() + p.speed(0) + p.getscreen().tracer(30,0) + p.left(90) + p.penup() + p.forward(-210) + p.pendown() + t = tree([p], 200, 65, 0.6375) + for x in t: + pass + print(len(p.getscreen().turtles())) + +def main(): + a=clock() + maketree() + b=clock() + return "done: %.2f sec." % (b-a) + +if __name__ == "__main__": + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/turtle.cfg b/Lib/turtledemo/turtle.cfg new file mode 100644 index 0000000000..bd89a741f9 --- /dev/null +++ b/Lib/turtledemo/turtle.cfg @@ -0,0 +1,10 @@ +width = 800 +height = 600 +canvwidth = 1200 +canvheight = 900 +shape = arrow +mode = standard +resizemode = auto +fillcolor = "" +title = Python turtle graphics demo. + diff --git a/Lib/turtledemo/two_canvases.py b/Lib/turtledemo/two_canvases.py new file mode 100644 index 0000000000..02d89db57e --- /dev/null +++ b/Lib/turtledemo/two_canvases.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +## DEMONSTRATES USE OF 2 CANVASES, SO CANNOT BE RUN IN DEMOVIEWER! +"""turtle example: Using TurtleScreen and RawTurtle +for drawing on two distinct canvases. +""" +from turtle import TurtleScreen, RawTurtle, TK + +root = TK.Tk() +cv1 = TK.Canvas(root, width=300, height=200, bg="#ddffff") +cv2 = TK.Canvas(root, width=300, height=200, bg="#ffeeee") +cv1.pack() +cv2.pack() + +s1 = TurtleScreen(cv1) +s1.bgcolor(0.85, 0.85, 1) +s2 = TurtleScreen(cv2) +s2.bgcolor(1, 0.85, 0.85) + +p = RawTurtle(s1) +q = RawTurtle(s2) + +p.color("red", (1, 0.85, 0.85)) +p.width(3) +q.color("blue", (0.85, 0.85, 1)) +q.width(3) + +for t in p,q: + t.shape("turtle") + t.lt(36) + +q.lt(180) + +for t in p, q: + t.begin_fill() +for i in range(5): + for t in p, q: + t.fd(50) + t.lt(72) +for t in p,q: + t.end_fill() + t.lt(54) + t.pu() + t.bk(50) + +## Want to get some info? + +#print(s1, s2) +#print(p, q) +#print(s1.turtles()) +#print(s2.turtles()) + +TK.mainloop() diff --git a/Lib/turtledemo/wikipedia.py b/Lib/turtledemo/wikipedia.py new file mode 100644 index 0000000000..0f274420c8 --- /dev/null +++ b/Lib/turtledemo/wikipedia.py @@ -0,0 +1,65 @@ +""" turtle-example-suite: + + tdemo_wikipedia3.py + +This example is +inspired by the Wikipedia article on turtle +graphics. (See example wikipedia1 for URLs) + +First we create (ne-1) (i.e. 35 in this +example) copies of our first turtle p. +Then we let them perform their steps in +parallel. + +Followed by a complete undo(). +""" +from turtle import Screen, Turtle, mainloop +from time import clock, sleep + +def mn_eck(p, ne,sz): + turtlelist = [p] + #create ne-1 additional turtles + for i in range(1,ne): + q = p.clone() + q.rt(360.0/ne) + turtlelist.append(q) + p = q + for i in range(ne): + c = abs(ne/2.0-i)/(ne*.7) + # let those ne turtles make a step + # in parallel: + for t in turtlelist: + t.rt(360./ne) + t.pencolor(1-c,0,c) + t.fd(sz) + +def main(): + s = Screen() + s.bgcolor("black") + p=Turtle() + p.speed(0) + p.hideturtle() + p.pencolor("red") + p.pensize(3) + + s.tracer(36,0) + + at = clock() + mn_eck(p, 36, 19) + et = clock() + z1 = et-at + + sleep(1) + + at = clock() + while any([t.undobufferentries() for t in s.turtles()]): + for t in s.turtles(): + t.undo() + et = clock() + return "runtime: %.3f sec" % (z1+et-at) + + +if __name__ == '__main__': + msg = main() + print(msg) + mainloop() diff --git a/Lib/turtledemo/yinyang.py b/Lib/turtledemo/yinyang.py new file mode 100644 index 0000000000..11d1f47cae --- /dev/null +++ b/Lib/turtledemo/yinyang.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +""" turtle-example-suite: + + tdemo_yinyang.py + +Another drawing suitable as a beginner's +programming example. + +The small circles are drawn by the circle +command. + +""" + +from turtle import * + +def yin(radius, color1, color2): + width(3) + color("black", color1) + begin_fill() + circle(radius/2., 180) + circle(radius, 180) + left(180) + circle(-radius/2., 180) + end_fill() + left(90) + up() + forward(radius*0.35) + right(90) + down() + color(color1, color2) + begin_fill() + circle(radius*0.15) + end_fill() + left(90) + up() + backward(radius*0.35) + down() + left(90) + +def main(): + reset() + yin(200, "black", "white") + yin(200, "white", "black") + ht() + return "Done!" + +if __name__ == '__main__': + main() + mainloop() |