Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Turtle graphics for PBCC/PBWin, plus PBDOS "DRAW" upgraded

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBWin/PBCC Turtle graphics for PBCC/PBWin, plus PBDOS "DRAW" upgraded

    TgDraw is a very substantial rewrite, expansion and improvement of a program that was posted on the PBCC forum [URL below] about two months ago. Petr Schreiber is the co-author. He programmed entirely in PBWin 8.04 while I worked entirely in PBCC 4.04; the program will run almost identically, and equally well, in either. Thanks to Petr's knowledge of double buffering, macros and other new-fangled esoterica, the program can run many times faster than its PBCC prototype, and that was already fast compared to VB or PBDOS.

    It is Freeware, and placed by us in the Public Domain.

    TgDraw is not a full-blown emulation of LOGO's Turtle Graphics because, among other things, it is written in PowerBASIC, and PowerBASIC is a compiler rather than an interpreter. What our program does is to implement the turtle's most basic commands (e.g., turn n degrees, go forward x steps) and to enable one to invoke them either directly or via the much more concise terminology of DRAW code. TgDraw thus emulates and extends
    DOS-BASIC's DRAW command, which is really a very powerful and useful mini-language for handling graphics data.

    All source code, demos, tutorials and documentation are in a single .ZIP file, which is attached to this post. The most important file in the ZIP is tgDraw.INC; it contains all the turtle and drawing engines and basic supporting subroutines. If you are familiar with the DOS-DRAW language you might well get by with just tgDraw.Inc and BareBonesTemplate.BAS, which lists the few lines that you need to get set for programming in a Windows version of PowerBASIC. There are, however, also numerous demos and tutorials, plus a QuickReference Card that covers all available tgDraw commands. The demos and tutorials are heavily commented. The syntax of tgDraw differs a bit from that of PBDOS, but we are betting that you will prefer it.

    We welcome your comments, critiques, suggestions and demos or related programs of your own. Post them, if you can, on http://powerbasic.com/support/pbforums/showthread.php?t=37325
    Attached Files
    Last edited by Emil Menzel; 26 Jun 2008, 09:55 AM.

  • #2
    'Elsewhere, Daniel Corbier gave this as an example of a LOGO program:
    ' to square repeat 4 [forward 50 right 90] end
    ' to flower repeat 36 [right 10 square] end
    ' flower

    This looks as if involves not just looping but two loops, one nested within the other.

    Until today we thought that our tgDraw program could not do this. But we were wrong. The documentation & demos in our .ZIP file will have to be updated accordingly.

    'The 'trick' is simply to send strings to FUNCTION tgDrawCheck first, before combining them to send to SUB tgDraw. TgDrawCheck deletes all spaces, capitalizes all text, and expands RPT statements, so that (e.g.) RPT2 (J50) becomes J50J50. Such strings can easily be concatenated. Obviously strings could get so big as to crash the program. But ours don't, and could easily be many times larger without causing any problem.


    Code:
    'Demo of nesting one RPT command within another
    'To run it, paste this code into one of the BareBonesTemplates in the .ZIP file
    'In the tgDraw macro language, Jn=jumpForward n steps; On=turnRight n degrees; Xn = RPTn times whatever is within the parentheses
    
    
    LOCAL square, flower AS STRING                  
    square = tgDrawCheck ("X4(j50 o90)")        
    flower = tgDrawCheck ("X36(o10" + square + ")" ) 
    tgClearScreen        'this sets X,Y pos to center of screen
    tgdraw (flower)
    tgUpdateScreen
    SLEEP 10000

    Comment


    • #3
      Our tgDraw program has by now been substantially expanded and improved. Please scrap the old versions, if you have them, and download the new. The attached files contain everything you need; if you download them you do not need the source code that is listed below. The source code is for those who like to browse. It includes tgDraw.INC, which is the heart & core of our program, and tgDrawer.BAS, a demo that amounts to a simple interpreter. Type in almost any statement you wish in the DRAW/Turtle graphics mini-language, and press Enter. Alternatively, you can draw with a mouse, if you really want to. The interpreter does have limitations compared to a compiled program, but it has its advantages too.

      tgDrawer.BAS is, coincidentally, for PCC only; it requires both a console screen and a graphics screen. All other programs may be compiled in either PBCC 5+ or PBWin 9+.

      SuperDemo.BAS (in the attached .ZIP file) illustrates almost all of the functions in tgDraw's repertoire. One thing is, however, missing -- Multi-Turtles, which Petr developed only in the past few days. So be sure not to miss the Multi-Turtle demos either. They in effect take tgDraw out of the old domain of LOGO and, at least potentially, into the domain of StarLOGO. (Cf., http://education.mit.edu/starlogo/ )

      NOTE ADDED 8/10/2009 6:30 PM USA Central Time. The version of tgDraw.Inc that was posted below yesterday was slightly out of date. As of now it has been changed & is up to date, & the same as the version that is in the .ZIP file. The out of date version will most likely not run the multi-turtle programs. Sorry about that.

      Code:
      '=========================================================================================
      '=                                                                                       =
      '=                                      TGDRAW.INC                                       =
      '=              Turtle graphics core functions, plus a DRAW macro language               =
      '=            by E.W. Menzel, Jr. (Emil Menzel) & Petr Schreiber, 2008, 2009             =
      '=                                                                                       =
      '=========================================================================================
      '=                             Save this file as tgDraw.inc                              =
      '=========================================================================================
      '=                                                                                       =
      '=                          FREEWARE; donated to Public Domain                           =
      '=                                                                                       =
      '=                           original QB prototype circa 1990                            =
      '=               revised for PBCC 4.04 and posted on PB forums 05/06/2008                =
      '=      revised for PBCC & PBWin, & SUB tgDraw added, Jun 2008, Mar 2009, Aug 2009       =
      '=                          requires either PBCC 5+ or PBWin 9+                          =
      '=                                                                                       =
      '=========================================================================================
      '=     This program is named after one of its core subroutines (SUB tgDraw), an          =
      '=     emulation & extension of DOS-BASIC's DRAW mini-language. It aims to be            =
      '=     95% compatible with DOS-BASIC's DRAW, but to also incorporate the                 =
      '=     the capabilities of true Turtle graphics, or "TG" for short.                      =
      '=                                                                                       =
      '=     To quote Bob Zale (March 2009 PowerBASIC forums):                                 =
      '=     "Actually, I think DRAW is a good option for a very select type of application.   =
      '=     It adds no extra graphic primitives, but rather just allows you to access         =
      '=     them in a different way... If you have a need to dynamically create a graphic     =
      '=     at run-time, DRAW can be very helpful."                                           =
      '=                                                                                       =
      '=     tgDraw is not literally a full-blown emulation of LOGO's Turtle Graphics          =
      '=     largely because it is written in a compiled language rather than in an            =
      '=     interpreter. What it does to implement the turtle's most basic commands           =
      '=     (e.g., turn n degrees, go forward x steps, repeat any move or sequence of         =
      '=     moves n times) and to enable one to invoke them either directly or via            =
      '=     the much more concise terminology of DRAW code.                                   =
      '=                                                                                       =
      '=     Quite simply, the DRAW [and tgDraw, and turtle] statement "draws the              =
      '=     graphic figure specified in a string expression. DRAW uses 'macro                 =
      '=     language' that lets you describe lines in relative terms, by                      =
      '=     specifying the distance & direction of graphics-cursor movements."                =
      '=                                                                                       =
      '=     That is a quote from the excellent overview of DRAW in "The Waite                 =
      '=     Groups' Microsoft Quick-BASIC Bible", Microsoft Press, 1990, pp 413 -             =
      '=     419. The syntax for the DRAW statement has varied somewhat in                     =
      '=     in different BASICs; tgDraw syntax is closest to that of an                       =
      '=     interpreted BASIC such as GWBASIC, vs a compiled BASIC such as QB.                =
      '=                                                                                       =
      '=     For a commercial-grade PBWin .DLL, see Chris Boss's EZGUI version                 =
      '=     of a "turtle-like" graphics: http://cwsof.com/                                    =
      '=     See H. Abelson & A. diSessa, Turtle geometry, MIT Press, 1986 for the full        =
      '=     mathematical power of turtle geometry and also the differences                    =
      '=     between turtle, vector & coordinate geometry                                      =
      '=                                                                                       =
      '=     For a good intro to turtle geometry on the Web see Brian Harvey's book:           =
      '=     http://www.cs.berkeley.edu/~bh/pdf/v1ch10.pdf                                     =
      '=     For very nice programming demos:  http://www.psinvention.com/Turtle.htm           =
      '=                                                                                       =
      '=                                                                                       =
      '=     Sierpinski triangle rendering by Petr Schreiber                                   =
      '=     ( conversion from thinBASIC original )                                            =
      '=     more info on Sierpinski triangle:                                                 =
      '=     http://en.wikipedia.org/wiki/Sierpinski_triangle                                  =
      '=                                                                                       =
      '=     more info on L systems:                                                           =
      '=     http://en.wikipedia.org/wiki/L-system#Example_6:_Sierpi.C5.84ski_triangle         =
      '=     W. McWorter tutorial:  http://spanky.triumf.ca/www/fractint/lsys/tutor.html       =
      '=     Robert Jessop Java applet: http://home.clara.net/niknak/fractal/                  =
      '=                                                                                       =
      '=========================================================================================
      
      #IF NOT %DEF(%WINAPI)
          #INCLUDE "WIN32API.INC"
      #ENDIF
      DECLARE FUNCTION MakeRotatedFont (BYVAL hDC AS DWORD, BYVAL FontName AS STRING, _
                                        BYVAL PointSize AS LONG, BYVAL Angle AS LONG, _
                                        BYVAL fBold AS LONG, BYVAL fItalic AS LONG, _
                                        BYVAL fUnderline AS LONG, BYVAL fStrikeThru AS LONG) AS DWORD
      
      'turtle primitive basic commands
      
      '-------------------------------------------------------------------------------
      '-                                   Equates                                   -
      '-------------------------------------------------------------------------------
      
      %TG_FALSE         = 0
      %TG_TRUE          = 1
      
      %TG_SINGLE_BUFFER = 1
      %TG_DOUBLE_BUFFER = 2
      
      %TG_BLACK         = 0
      %TG_BLUE          = 1
      %TG_GREEN         = 2
      %TG_CYAN          = 3
      %TG_RED           = 4
      %TG_MAGENTA       = 5
      %TG_BROWN         = 6
      %TG_WHITE         = 7
      %TG_GRAY          = 8
      %TG_LIGHTBLUE     = 9
      %TG_LIGHTGREEN    = 10
      %TG_LIGHTCYAN     = 11
      %TG_LIGHTRED      = 12
      %TG_LIGHTMAGENTA  = 13
      %TG_YELLOW        = 14
      %TG_LIGHTWHITE    = 15
      
      %TG_DEFAULT       = 0
      
      '-------------------------------------------------------------------------------
      '-                                    Types                                    -
      '-------------------------------------------------------------------------------
      
      TYPE TurtleType
         ID AS LONG      ' Unique identifier of turtle
         HB AS EXT       'heading BASE angle of turtle, in degrees
         H AS EXT        'heading angle of turtle, in degrees
         PS AS LONG         'PenStatus down (to draw) or up (move but don't draw)
         RTS AS LONG        '0 or -1. -1=Return to start after a jump. For tDRAW "NJ" command
         PX AS SINGLE       'present location, X axis
         PY AS SINGLE
         NX AS SINGLE       'new location, X axis
         NY AS SINGLE
         DistGap AS SINGLE  'When User is drawing with a mouse (e.g., in tgDrawer.BAS),
                            'how far apart (in pixels) must 2 points be before program assumes
                            'it should move without plotting? (cf DRAW BMx,y versus DRAW Mx,y)?
                            'If DistGap <10, "lines" might be spotty &/or drawing might be slow.
         COLOR AS LONG      'foreground color for draw
         Background AS LONG 'background color
         WIDTH AS SINGLE    'pen width in pixels, or window units
         LineStyle AS LONG  '0=Solid lines (default);1=Dash;2=Dot;3=DashDot;4=DashDotDot
                            'LineStyle > 0 requires than Width = 1. See PBCC/PBWin GRAPHIC STYLE
         PAUSE AS LONG      'millisec SLEEP after EACH pen move+draw (in sub tgForward)
                            'zero sleep is OK
         SCALE AS SINGLE    'multiply all (SUB tgForward) move-sizes by this value
         kee AS LONG        'mouse click or keypress
         doubleBuffer AS BYTE
         AttachGraphicHandle AS DWORD 'its value is set by the last call to tgGraphicAttach
      
         canvasWidth  AS LONG  'size of current turtle window
         canvasHeight AS LONG
         HomeX AS SINGLE       'redefinable place to return to with tgClearScreen...
         HomeY AS SINGLE       '& tgHome (K) commands... see also tgSetDefaults
         LoRandom AS LONG       'Specify low range of values for random numbers
         HiRandom AS LONG       'See RANDSET (alias @)
         FontName AS STRING*15  'for GRAPHIC PRINT font
         FontPoints AS LONG     'scalable print size for GRAPHIC PRINT... can go >= 99
         FontStyle  AS LONG     'print style 0=normal 1=bold 2=italic 4=underline 8=strikeout
      END TYPE
      GLOBAL turtle AS turtleType
      GLOBAL pTurtle as turtleType PTR
      GLOBAL idTurtle as long
      '-------------------------------------------------------------------------------
      '-                           Macros, subs, functions                           -
      '------------------------------------------------------------------------------
      ' -- To make program compile under PB/WIN
      #IF NOT %DEF(%PB_CC32)
        MACRO STDOUT = MSGBOX
      #ENDIF
      
      MACRO Pi = 3.141592653589793#
      MACRO Degrees2Rads = 0.0174532925199433##  '0.0174532925199#   'Pi/180
      MACRO ValidNum = "+-.0123456789,"       'used in SUB tgDraw
      MACRO ValidCmd = "CSPMRFDGLHUEAIJKOQVWXYZ?*!/$#&@~^>" 'used in SUB tgDraw
      MACRO RndNum = 666&                               'code val for "make up a random val"
      MACRO Arrow =  "V20 NI14 o40 NI14 V20"      'tgdraw it, to show turtle direction
      
      ' -- Should be called first, before any drawing
      SUB tgAttachGraphic( hWnd AS DWORD, id AS LONG, tgType AS LONG )
      
        IF tgType = %TG_SINGLE_BUFFER THEN
          GRAPHIC ATTACH hWnd, id
          turtle.doubleBuffer = %TG_FALSE
        ELSE
          GRAPHIC ATTACH hWnd, id, REDRAW
          turtle.doubleBuffer = %TG_TRUE
        END IF
      
         turtle.AttachGraphicHandle = hWnd  'save, for use in e.g. tgReadFile's loading of .BMP files
        ' -- Gets the canvas size and so on
        CALL tgSetDefaults()
      END SUB
      
      SUB tgSetDefaults()
        turtle.H          = 0
        turtle.HB         = 0
        turtle.PS         = 0
        turtle.RTS        = 0
        turtle.px         = 0
        turtle.py         = 0
        turtle.nx         = 0
        turtle.ny         = 0
        turtle.DistGap    = 10
        turtle.Color     = RGB(0,0,0)
        turtle.background = RGB(255,255,255)
        turtle.width = 1
        turtle.linestyle = 0
        turtle.pause = 0
        turtle.scale = 1
        GRAPHIC GET CLIENT TO turtle.canvasWidth, turtle.canvasHeight
        turtle.HomeX = turtle.canvasWidth / 2
        turtle.HomeY = turtle.canvasHeight / 2
        turtle.LoRandom = 0
        turtle.HiRandom = 0
        turtle.FontName = "Times New Roman"   'STRING*15 (fixed size unless you revise TurtleType above)
        turtle.FontPoints = 8
        turtle.FontStyle  = 0
      END SUB
      
      ' -- Sets active turtle
      ' -- tgAttachGraphic MUST be called after this for the first time!
      SUB tgSetTurtle( byref newTurtle as turtleType )
        local memorySoup as string
      
        ' -- If there was some active, we will copy the data back
        if pTurtle <> 0 then
          memorySoup = peek$(varptr(turtle), sizeof(turtleType))
          poke$ pTurtle, memorySoup
        end if
      
        ' -- Generate ID for new turtle
        if newTurtle.ID = 0 then
          incr idTurtle
          newTurtle.ID = idTurtle
        end if
      
        ' -- Bind new turtle
        pTurtle = varptr(newTurtle)
        memorySoup = peek$(pTurtle, sizeof(turtleType))
        poke$ varptr(turtle), memorySoup
      
      END SUB
      
      ' -- Gets active turtle ID identifier (positive number)
      ' -- It returns %TG_DEFAULT for default turtle
      function tgGetTurtleID() as long
        function = turtle.ID
      end function
      
      
      ' -- Updates the canvas bitmap, only in case of double buffer mode
      MACRO tgUpdateScreen()
        IF turtle.doubleBuffer = %TG_TRUE THEN GRAPHIC REDRAW
      END MACRO
      
      ' -- Sets foreground and background color for drawing in RGB
      MACRO tgSetColorRGB( f, b )
        turtle.Color     = f
        turtle.background = b
        GRAPHIC COLOR turtle.Color, turtle.background
      END MACRO
      
      ' -- Sets foreground and background color for drawing in DOS like numbers
      MACRO tgSetColor( f, b )
        turtle.Color     = tgColorVal(f)
        turtle.background = tgColorVal(b)
        GRAPHIC COLOR turtle.Color, turtle.background
      END MACRO
      
      ' -- Sets width
      MACRO tgSetWidth( nWidth )
        turtle.width     = nwidth
      END MACRO
      
      ' -- Clears screen using current background color
      MACRO tgClearScreen
          GRAPHIC CLEAR turtle.Background   'clear graphic window
          GRAPHIC SET POS (turtle.HomeX, turtle.HomeY)
          IF turtle.doubleBuffer = %TG_FALSE THEN GRAPHIC REDRAW
          turtle.PX = turtle.HomeX
          turtle.PY = turtle.HomeY
          turtle.H = 0       'angle turtle is now headed
          turtle.HB = 0      'base angle
          tgPenDown
      END MACRO
      
      ' -- Centers cursor
      MACRO tgHome()
          IF turtle.doubleBuffer = %TG_FALSE THEN GRAPHIC REDRAW
          GRAPHIC SET POS (turtle.HomeX, turtle.homeY)
          turtle.PX = turtle.HomeX
          turtle.PY = turtle.HomeY
          turtle.H  = 0      'angle turtle is now headed
          turtle.HB = 0      'base angle
          tgPenDown
      END MACRO
      
      ' -- Sets cursor at position
      MACRO tgSetPos( x, y )
      
          GRAPHIC SET POS (x, y)
          turtle.PX = x
          turtle.PY = y
          turtle.H  = 0       'angle turtle is now headed
          turtle.HB = 0      'base angle
          tgPenDown()
      
      END MACRO
      
      ' -- Turtle Basic Commands
      'Forward & Backward are the turtle counterparts for the DOS DRAW commands RDLREFGH and M+x,-y
      'NOTE: For the tgDraw codes Jn (Jump forward) and In (jump backward) check
      'beforehand if n=0, and if so, make n=1.
      
      MACRO tgForward (F1)
            IF turtle.Scale <= 0 THEN turtle.Scale = 1 'assume it's an error
            turtle.NX = turtle.PX + (COS((turtle.HB+turtle.H) * Degrees2Rads) * F1 * turtle.Scale)
            turtle.NY = turtle.PY + (SIN((turtle.HB+turtle.H) * Degrees2Rads) * F1 * turtle.Scale)
            tgPlotter
      END MACRO
      
      MACRO tgBackward (F1)
            IF turtle.Scale <= 0 THEN turtle.Scale = 1 'assume it's an error
            turtle.NX = turtle.PX - (COS((turtle.HB+turtle.H) * Degrees2Rads) * F1 * turtle.Scale)
            turtle.NY = turtle.PY - (SIN((turtle.HB+turtle.H) * Degrees2Rads) * F1 * turtle.Scale)
            tgPlotter
      END MACRO
      
      MACRO tgRight (R1)
          turtle.H = turtle.H + R1
          IF turtle.H > 360 THEN
              turtle.H = turtle.H -360
          ELSEIF turtle.H < -360 THEN
              turtle.H = turtle.H +360
          END IF
      END MACRO
      
      MACRO tgLeft (L1)
         turtle.H = turtle.H - L1
         IF turtle.H > 360 THEN
             turtle.H = turtle.H -360
         ELSEIF turtle.H < -360 THEN
             turtle.H = turtle.H +360
         END IF
      END MACRO
      
      ' -- Turtle Pen status
      'If you use tgDraw code to execute turtle commands,
      'pendown is the default, and the code for penup
      'or "don't draw" is the prefix "B" on any given command
      'E.g. BR4 means move right 4 units, with penup.
      
      MACRO tgPenDown
        turtle.PS = -1
      END MACRO
      
      MACRO tgPenUp
         turtle.PS = 0
      END MACRO
      
      '-- Turtle add-ons
      MACRO tgStrafeLeft (F1)
            IF turtle.Scale <= 0 THEN turtle.Scale = 1 'assume it's an error
            turtle.NX = turtle.PX + (COS((turtle.HB+turtle.H+90) * Degrees2Rads) * F1 * turtle.Scale)
            turtle.NY = turtle.PY + (SIN((turtle.HB+turtle.H+90) * Degrees2Rads) * F1 * turtle.Scale)
            tgPlotter
      END MACRO
      
      MACRO tgStrafeRight (F1)
            IF turtle.Scale <= 0 THEN turtle.Scale = 1 'assume it's an error
            turtle.NX = turtle.PX + (COS((turtle.HB+turtle.H-90) * Degrees2Rads) * F1 * turtle.Scale)
            turtle.NY = turtle.PY + (SIN((turtle.HB+turtle.H-90) * Degrees2Rads) * F1 * turtle.Scale)
            tgPlotter
      END MACRO
      
      'FUNCTION tgColorVal --- DOS-style colors, except that you can customize them
      'Any RGB color, for foreground and background, can be set with the tgDraw version of Cn
      'See the code for Cn in SUB tgDraw
      'FOOTNOTE for historians: DOS colors were not actually limited to only 16 values; there was
      'also the PALLETTE statement, by means of which color values could be varied. It might therefore
      'be nice to enhance tgColorVal to emulate PALLETTE. But as textbooks too often say, we leave that
      'as an exercise for the student.
      FUNCTION tgColorVal(Cval AS LONG) AS LONG
             STATIC again AS LONG
             LOCAL cv AS LONG
      
             IF NOT again THEN
                 again=-1
                 DIM ColorValue(15) AS STATIC LONG
                 ColorValue(%TG_BLACK)        =RGB(0,0,0)
                 ColorValue(%TG_BLUE)         =RGB(0,0,128)
                 ColorValue(%TG_GREEN)        =RGB(0,128,0)
                 ColorValue(%TG_CYAN)         =RGB(0,128,128)
                 ColorValue(%TG_RED)          =RGB(128,0,0)
                 ColorValue(%TG_MAGENTA)      =RGB(128,0,128)
                 ColorValue(%TG_BROWN)        =RGB(128,64,0)
                 ColorValue(%TG_WHITE)        =RGB(192,192,192)
                 ColorValue(%TG_GRAY)         =RGB(128,128,128)
                 ColorValue(%TG_LIGHTBLUE)    =RGB(0,0,255)
                 ColorValue(%TG_LIGHTGREEN)   =RGB(0,255,0)
                 ColorValue(%TG_LIGHTCYAN)    =RGB(0,255,255)
                 ColorValue(%TG_LIGHTRED)     =RGB(255,0,0)
                 ColorValue(%TG_LIGHTMAGENTA) =RGB(255,0,255)
                 ColorValue(%TG_YELLOW)       =RGB(255,255,0)
                 ColorValue(%TG_LIGHTWHITE)   =RGB(255,255,255)
             END IF
      
             cv=Cval
             IF cv < %TG_BLACK OR cv > %TG_LIGHTWHITE THEN cv = %TG_LIGHTWHITE
             FUNCTION = ColorValue(cv)
      
      END FUNCTION
      
      MACRO tgPlotter
             IF turtle.PS THEN   'if pen is down to draw
                 GRAPHIC COLOR turtle.Color, turtle.Background
                 GRAPHIC WIDTH turtle.WIDTH
                 GRAPHIC STYLE turtle.linestyle
                 GRAPHIC LINE (turtle.PX,turtle.PY)-(turtle.NX, turtle.NY) 'this also sets POS to NX,NY
                 IF turtle.RTS THEN
                     GRAPHIC SET POS (turtle.PX,turtle.PY)  'tgDraw "N" prefix was used, so return to start pos
                     turtle.NX = turtle.PX
                     turtle.NY = turtle.PY
                 ELSE
                     turtle.PX = turtle.NX
                     turtle.PY = turtle.NY
                 END IF
                 IF turtle.doubleBuffer = %TG_FALSE OR turtle.pause THEN GRAPHIC REDRAW
                 SLEEP turtle.pause
             ELSE
                 IF turtle.RTS THEN
                     GRAPHIC SET POS (turtle.PX,turtle.PY) 'tDRAW "N" prefix is used; return to start
                     turtle.NX = turtle.PX
                     turtle.NY = turtle.PY
                 ELSE
                     GRAPHIC SET POS (turtle.NX,turtle.NY)
                     turtle.PX = turtle.NX
                     turtle.PY = turtle.NY
                 END IF
             END IF
      END MACRO
      
      SUB tgPrint (Pr AS STRING)
          LOCAL A AS STRING
          LOCAL hDC, hFont AS DWORD
      
          IF Pr="?" OR Pr="" THEN
              EXIT SUB
          ELSEIF LEN(Pr) > 1 AND LEFT$(Pr,1)="?" THEN
              A$= MID$(Pr,2)
          ELSE
              A$= Pr
          END IF
          IF turtle.HB = 0 AND turtle.FontPoints <= 40 THEN
              GRAPHIC FONT turtle.FontName, turtle.FontPoints, Turtle.FontStyle
              GRAPHIC SET POS (INT(turtle.PX), INT(turtle.PY)) 'should not be necessary, but it seems to be
              GRAPHIC PRINT A$
          ELSE
              '--------- from textrotate.bas, a PowerBASIC Sample program --------
              ' Print some rotated text, Create a rotated font, select it into the
              ' Graphic control's DC, print text and delete the rotated font object
              ' to avoid memory leaks. Remember that for example text width becomes
              ' text height with a 90 degree font..
              '------------------------------------------------------------------
              GRAPHIC GET DC TO hDC
              hFont = MakeRotatedFont(hDC, TRIM$(turtle.FontName), INT(turtle.FontPoints), turtle.HB * 10, %FW_BOLD, 1, 0, 0)
              hFont = SelectObject(hDC, hFont)
              GRAPHIC SET POS (INT(turtle.PX), INT(turtle.PY)) 'this should not be necessary, but it seems to be
              GRAPHIC PRINT A$
              DeleteObject SelectObject(hDC, hFont)
         END IF
      END SUB
      
      ' Most "DRAW" code that was written for DOS BASIC will run fine with SUB tgDraw.
      ' FUNCTION tgTextDrawCode (which replaces Emil Menzel's SUB DrawText, circa 1989)
      ' is a case in point. The draw code it uses is exactly the same as it was originally.
      ' The only DRAW code that will need modification is that which uses Sn (to Scale).
      ' DOS DRAW sets the scaling factor to 4/n, and normal size to 4, and it uses
      ' integer math. tgDRAW uses single precision numbers, and scale size = n, and
      ' the default size is 1.0....
      '
      'TIP: If speed is of the essence, consider storing the words or phrases that you
      'translate into code with FUNCTION tgTextDrawCode, in "higher order" string arrays.
      
      'TIP 2: The array T$() below obviously does not have to be used only for letters and
      'numbers. There is nothing to prevent you from also including code for shapes, pictures,
      'or whatever else you can represent in the tgDraw language. And not just turtle moves,
      'but also coding for color, size, penwidth, and even time delays can be part of the string.
      
      FUNCTION tgTextDrawCode (txt AS STRING) STATIC AS STRING
        DIM Nt AS LONG, txt2 AS STRING
        DIM XX AS STRING, TextToDraw AS STRING
        DIM I AS LONG, C AS LONG
        DIM again AS STATIC LONG
        DIM tt AS STATIC STRING
      
        IF again = 0 THEN
          tt$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 .,:;/-"
          REDIM T(44) AS STATIC STRING
          Nt = UBOUND(T$)
          GOSUB tFONT
          again = -1
        END IF
      
        txt2$ = UCASE$(txt$)
        IF txt2$ = "" THEN EXIT FUNCTION
      
        TextToDraw$ = ""
        FOR I = 1 TO LEN(txt$)
          XX$ = MID$(txt2$, I, 1)
          C = INSTR(tt$, XX$)
          IF C > 0 AND C <= Nt THEN
             TextToDraw$ = TextToDraw$ + T$(C)
          END IF
        NEXT I
      
        FUNCTION=TextToDraw$
        EXIT FUNCTION
      
      
          tFONT:
          'the letters A-Z (DRAW code found in a QB or PBDOS achive)
          T$(1) = "BR1 U4 E2 F2 D2 L4 R4 D2 BR2"
          T$(2) = "BR1 U6 R3 F1 D1 G1 L2 BR2 F1 D1 G1 L3 BR6"
          T$(3) = "BR5 BU5 H1 L2 G1 D4 F1 R2 E1 BF1 BR1"
          T$(4) = "BR1 U6 R3 F1 D4 G1 L3 BR6"
          T$(5) = "BR1 U6 R4 BD3 BL2 L2 D3 R4 BR2"
          T$(6) = "BR1 U6 R4 BD3 BL2 L2 BD3 BR6"
          T$(7) = "BR5 BU5 H1 L2 G1 D4 F1 R2 E1 U1 L1 BD2 BR3"
          T$(8) = "BR1 U6 BD3 R4 BU3 D6 BR2"
          T$(9) = "BR1 R1 U6 L1 R2 L1 D6 R1 BR2"
          T$(10) = "BR5 BU6 D5 G1 L2 H1 BD1 BR6"
          T$(11) = "BR1 U6 BR4 G3 F3 BR2"
          T$(12) = "BR1 U6 BD6 R4 BR2"
          T$(13) = "BR1 U6 F3 E3 D6B R2"
          T$(14) = "BR1 U6 F6 U6 BD6 BR2"
          T$(15) = "BR5 BU5 H1 L2 G1 D4 F1 R2 E1 U4 BD5 BR2"
          T$(16) = "BR1 U6 R4 F1 D1 G1 L2 BD3 BR5"
          T$(17) = "BR5 BU5 H1 L2 G1 D4 F1 R2 E1 U4 BD4 H1 F2 BR2"
          T$(18) = "BR1 U6 R3 F1 D1 G1 L2 F3 BR2"
          T$(19) = "BR5 BU5 H1 L2 G1 D1 F1 R2 F1 D1 G1 L2 H1 BD1 BR6"
          T$(20) = "BR1 BU6 R4 L2 D6 BR4"
          T$(21) = "BR1 BU6 D5 F1 R2 E1 U5 BD6 BR2"
          T$(22) = "BR1 BU6 D4 F2 E2 U4 BD6 BR2"
          T$(23) = "BR1 BU6 D6 E2 F2 U6 BD6 BR2"
          T$(24) = "BR1 E6 BL6 F6 BR2"
          T$(25) = "BR1 BU6 F2 E2 BG2 D4 BR4"
          T$(26) = "BR1 BU6 R6 G6 R6 BR2"
          'NUMBERS
          T$(27) = "BR1 BU5 E1 D6 L1 R2 BR2"
          T$(28) = "BR1 BU5 E1 R2 F1 D1 G4 R4 BR2"
          T$(29) = "BR1 BU6 R4 G2 F2 D1 G1 L2 H1 BD1 BR6"
          T$(30) = "BR4 U6 G3 R4 BD3 BR2"
          T$(31) = "BR1 BU1 F1 R2 E1 U1 H1 L3 U3 R4 BD6 BR2"
          T$(32) = "BR3 BU6 L1 G1 D4 F1 R2 E1 U1 H1 L2 G1 BD2 BR6"
          T$(33) = "BR1 BU6 R4 G3 D3 BR4"
          T$(34) = "BR1 BU1 U1 E1 R2 E1 U1 H1 L2 G1 D1 F1 R2 F1 D1 G1 L2 H1 BD1 BR6"
          T$(35) = "BR5 BU4 G1 L2 H1 U1 E1 R2 F1 D4 G1 L1 BR4"
          T$(36) = "BR5 BU5 H1 L2 G1 D4 F1 R2 E1 U4 BD5 BR2"
      
          'SPACE
          T$(37) = "BR7"
          '
          T$(38) = "BR2 L1 U1 R1 D1 BR2"         'PERIOD
          T$(39) = "BR2 L1 U1 R1 D2 G1 BE1 BU1 BR2"        'COMMA
          T$(40) = "BR2 L1 U1 R1 D1 BU4 L1 U1 R1 D1 BD4 BR2"        'COLON
          T$(41) = "BR2 L1 U1 R1 D2 G1 BE1 BU5 L1 U1 R1 D1 BD4 BR2"    'SEMI-COLON
          T$(42) = "E6 BD6 BR3"                             'SLASH /
          T$(43) = "BR2 BU3 R3 BD3 BR3"        'DASH -
      
        RETURN
      
      END FUNCTION
      '============== for ExpansionTest. by Petr Schreiber =========
      %BAD_INPUT = -1
      FUNCTION findMatchingBracket( BYREF str AS STRING, npos AS LONG ) AS LONG
        REGISTER i AS LONG
        LOCAL nLevel AS LONG
        DIM Char(1 TO LEN(str)) AS STRING * 1 AT STRPTR(str)
      
        FOR i = nPos TO LEN(str)
      
          IF Char(i) = "(" THEN
            INCR nLevel
          ELSEIF Char(i) = ")" THEN
            DECR nLevel
            IF nLevel = 0 THEN
              FUNCTION = i
              EXIT FUNCTION
            END IF
          END IF
      
        NEXT
      
      END FUNCTION
      
      'tgDrawCheck formats a string to be processed by tgDraw
      'and implements the Turtle command "To Repeat"
      FUNCTION tgDrawCheck (Drawstring AS STRING) AS STRING
          LOCAL I,J,K,L,M AS LONG
          LOCAL A,B,D,Dr AS STRING
      
          Dr$=Drawstring$
          L=LEN(Dr$)
           'check for ? (GRAPHIC PRINT) and * (textDraw) and ! (STDOUT) statements.
           'Assume only 1 print command per line , & no other commands following it
           'i.e., any additional commands with be printed out rather than executed
          I = INSTR(Dr$, ANY "*?!")
          IF I > 0 THEN
              B$ = MID$(Dr$,I)
              IF LEFT$(B$,1) = "*" THEN
                  B$=B$+CHR$(219)   'pad w/ a non-printing char, just in case
                  B$ = tgTextDrawCode(MID$(B$,2))  'convert text to draw code & delete the print cmd *
              END IF
              B$=CHR$(219) + B$   'don't let print cmds be 1st char on a line
              Dr$ = " " + Dr$  'pad, just in case
              J=I+1
              Dr$ = LEFT$(Dr$,J-1)  'anything that preceded the print command
          ELSE
              B$=""
          END IF
      
          'fontname must be the last statement in Dr$, and can include spaces
          I= INSTR(UCASE$(Dr$),"FONTNAME")
          IF I THEN
              Dr$=(MID$(Dr$,I+9))+" "
              turtle.FontName = TRIM$(Dr$)
              GRAPHIC FONT TRIM$(Dr$)     '***SHOULD USE INSTEAD Graphic set font
              FUNCTION = ""
              EXIT FUNCTION
          END IF
          REPLACE " " WITH "" IN Dr$          'purge all spaces
          Dr$=CHR$(32)+(TRIM$(UCASE$(Dr$))) + CHR$(32) 'capitalize, & pad ends
          IF INSTR (Dr$, "FONT") THEN REPLACE "FONT" WITH "~" IN Dr$
          IF INSTR(Dr$, "REFRESH") THEN REPLACE "REFRESH" WITH "&" IN Dr$
          IF INSTR(Dr$, "RPT") THEN REPLACE "RPT" WITH "X" IN Dr$
          IF INSTR(Dr$, "RESET") THEN REPLACE "RESET" WITH "#" IN Dr$
          IF INSTR(Dr$, "DISTGAP") THEN REPLACE "DISTGAP" WITH ">" IN Dr$
          IF INSTR(Dr$, "SAVESCREEN") THEN REPLACE "SAVESCREEN" WITH "$" IN Dr$
          IF INSTR(Dr$,"RANDSET") THEN REPLACE "RANDSET" WITH "@" IN Dr$
          A$=TRIM$(STR$(RndNum))
          IF INSTR(Dr$,"RANDOM")THEN REPLACE "RANDOM" WITH A$ IN Dr$
          IF INSTR(Dr$,"ARROW") THEN REPLACE "ARROW" WITH "^" IN Dr$  'show turtle's current direction
          'expand procedure by Petr Schreiber
          LOCAL sPos, posX, posOpen, posClose, nTimes, restPos AS LONG
          LOCAL rpt, addStr AS STRING
      
          ' -- Iterate until all eXpansions done
          sPos = 1
          DO
            ' -- Find X
            posX = INSTR(sPos, Dr$, "X")
            IF posX = 0 THEN EXIT LOOP
      
            ' -- Get the apropriate bracket
            posOpen = INSTR(posX, Dr$, "(")
            'trap a potentially bad bug -- (user could enter X accidentally, e.g. in tgDrawer interpreter)
            IF posOpen = 0 THEN EXIT LOOP
      
      
            ' -- Extract number of time   X<number>(
            nTimes  = VAL(MID$(Dr$, posX+1, posOpen-posX-1))
      
            ' -- Find matching bracket, NOT the nearest one
            posClose= findMatchingBracket(Dr$, posOpen)
      
            ' -- Extract part to repeat
            rpt = MID$(Dr$, posOpen+1, posClose-posOpen-1)
      
            ' -- Just do it :)
            rpt = REPEAT$(nTimes, rpt)
      
            ' -- Cut the X<number>( ... ) part and replace it with repetition safely
            Dr$ = STRDELETE$(Dr$, posX, posClose-posX+1)
            Dr$ = STRINSERT$(Dr$, rpt, posX)
      
          LOOP
      
          ' -- Add the possibly trimmed text
          Dr$ = Dr$ + B$
      
          FUNCTION=Dr$
      END FUNCTION
      
      'tgAddPos, by Petr Schreiber.
      'This SUB is for the DOS DRAW commands RDLREFGH and M+x,-y
      'For true Turtle geometry, use Left(angle), Forward(Distance) instead
      'NOTE:  RDLREFGH are all valid commands, by themselves, even if not followed
      'by a numeral: If n=0 or null then n=1. SUB tgDraw assures this before calling tgAddPos.
      SUB tgAddPos( BYVAL x AS SINGLE, BYVAL y AS SINGLE )
        x = x * turtle.scale
        y = y * turtle.scale
        IF turtle.HB THEN
            'rotation is needed
            turtle.NX = turtle.PX + COS(turtle.HB*Degrees2Rads)*x + COS((turtle.HB+90)*Degrees2Rads)*y
            turtle.NY = turtle.PY + SIN(turtle.HB*Degrees2Rads)*x + SIN((turtle.HB+90)*Degrees2Rads)*y
        ELSE
            'The formulas above would still be OK, but this is obviously faster
            turtle.NX = turtle.PX + x
            turtle.NY = turtle.PY + y
        END IF
        tgPlotter
      END SUB
      
      'tgDraw: An emulation & hopefully an upgrade
      'of DOS BASIC's "DRAW" graphics mini-language
      'by Emil Menzel, 2008
      'but Petr Schreiber's SUB tgAddPos does the hardest job -- rotations
      'SUB tgHelpOnDraw gives a complete listing of tgDraw's commands
      'The first 13 commands are from DOS-DRAW and the rest are new
      'The manuals for (e.g.) GWBASIC, QuickBASIC or PBDOS should be consulted for more details.
      
      SUB tgDraw (Drw AS STRING) STATIC
          LOCAL L,K,comma,FillColor, Pcolor AS LONG
          LOCAL I, J, P AS LONG
          LOCAL A,B,C, D, Dr, E AS STRING
          LOCAL x0, y0, z0 AS SINGLE
          LOCAL cmd, relativeOrAbs, fontSize,fontStyle AS LONG
          IF LEN(Drw) < 1 THEN EXIT SUB
          IF turtle.Scale <=0 THEN turtle.Scale = 1 'change default as you wish
          Dr$=tgDrawCheck(Drw$) 'work with a copy; leave original string as is
                       'clean up DRAW string; expand any RPT (repeats); translate text to drawcode
          L=LEN(Dr$)           'length can change, in tgDrawCheck
          IF L<1 THEN EXIT SUB
      
          'MACRO ValidNum = "+-.0123456789,"   'defined at outset of file
          'MACRO ValidCmd = "CSPMRFDGLHUEAIJKOQVWXYZ?*!/$#&@~^>"
          'other valid chars are "BN"
          'also allowed: T, as in TA command
          'NOTE: We allow decimal point & non-integer numbers though DOS DRAW doesn't
          'NOTE2: IJKOQVWYZ!?* are not in DOS BASIC DRAW
          'NOTE3: X is a DOS BASIC DRAW command but we do not need it
          'NOTE3: There are no non-reserved letters, at least between a-z and A-Z.
          'locate each actual command, in the Drawstring
          I=2   'Drawstring should be padded with a space on each end
          DO UNTIL I > = L
              A$= MID$(Dr$,I,1)
              cmd=INSTR(ValidCmd,A$)
              IF cmd >0 THEN
                  GOSUB DoIt
                  I = J - 1
              END IF
              INCR I
          LOOP
          IF turtle.doubleBuffer = %TG_FALSE THEN GRAPHIC REDRAW
          EXIT SUB
      
          '================ gosub =============================
      #ALIGN 16
      DoIt:
              'process a single DRAW command
              'A$=MID$(Dr$,I,1)  'command; cmd is command number
              B$=MID$(Dr$,I-1,1) 'prefix -- B,N,T or junk
              D$=""              'for suffix
              FOR J=I+1 TO L
                  C$=MID$(Dr$,J,1) 'suffix -- could be 1 or more numbers
                  IF INSTR (ValidNum,C$) <1 THEN EXIT FOR
                  D$=D$+C$
              NEXT
              IF LEN(D$) THEN
                 x0=VAL(D$)
                 relativeOrAbs = INSTR ("+-", LEFT$(D$,1))  'treat as an INCR or relative change
      
                 IF relativeOrAbs AND INSTR("CQP", A$) THEN
                    'split a color value into R,G,B components
                    DIM MyColor(1 TO 3) AS BYTE AT VARPTR(Turtle.Color)
                    DIM MyBackground(1 TO 3) AS BYTE AT VARPTR(Turtle.Background)
                 END IF
      
                 IF x0 = RndNum THEN
                     IF turtle.LoRandom <> turtle.HiRandom THEN
                       IF turtle.LoRandom = 0 AND turtle.HiRandom = 1 THEN
                         x0 = RND
                       ELSE
                         'integer val
                         x0 = RND(turtle.LoRandom, turtle.HiRandom)
                       END IF
                     ELSE
                       'see below, defaults for each variable
                     END IF
                 END IF
              ELSE
                 x0 = 0
                 relativeOrAbs = 0
              END IF
              IF B$="B" THEN turtle.PS = 0 ELSE turtle.PS = -1     'B=penup. Pendown is DRAW's default
              IF B$="N" THEN turtle.RTS = -1 ELSE turtle.RTS = 0   'N=return to start after plot
              turtle.NX=turtle.PX
              turtle.NY=turtle.PY
      
              IF cmd < 5 THEN
                'DOS DRAW stuff
                 SELECT CASE cmd
                     CASE 1 '"C"  Color. In DOS DRAW it was Cn where n is 0-16
                         y0 = TALLY(D$, ",")
                         IF ABS(x0) = RndNum THEN
                               turtle.Color = RGB(RND(0,255), RND(0,255), RND(0,255))
                         ELSEIF y0 = 2 THEN
                             IF relativeOrAbs =%TG_FALSE THEN
                               turtle.Color = RGB( VAL(PARSE$(D$, ",", 1)), VAL(PARSE$(D$, ",", 2)), VAL(PARSE$(D$, ",", 3)) )
                             ELSE
                               turtle.Color = RGB( CLNG (MyColor(1))+VAL(PARSE$(D$, ",", 1)), CLNG (MyColor(2))+VAL(PARSE$(D$, ",", 2)), CLNG (MyColor(3))+VAL(PARSE$(D$, ",", 3)) )
                             END IF
                         ELSE
                              'Assume DOS colors 0-16
                              IF RelativeOrAbs = %TG_FALSE THEN
                                  IF x0 >=%TG_BLACK AND x0 <= %TG_LIGHTWHITE THEN turtle.Color = tgColorVal(INT(x0))
                              ELSE
                                  'what is current color?
                                  FOR K=%TG_BLACK TO %TG_LIGHTWHITE
                                      IF turtle.Color = tgColorVal(K) THEN
                                          y0 = (ABS(K + x0)) MOD 16    'incr color
                                          turtle.color = (tgColorVal(INT(y0)))
                                          EXIT FOR
                                      END IF
                                  NEXT
                              END IF
                         END IF
                         tgSetColorRGB (turtle.Color, turtle.Background)
                     CASE 2 '"S"  Scale or number of pixels per jump
                         IF ABS(x0) = RndNum THEN x0 = SGN(x0)* RND (1,10)
                         IF RelativeOrAbs = %TG_FALSE THEN
                             turtle.Scale = x0
                         ELSE
                             turtle.Scale = turtle.Scale + x0
                         END IF
                         IF turtle.Scale <=0 THEN turtle.Scale =1
      
                             'Note! If you want to be completely consistent with PBDOS,
                         'S should be x0/4 ; 4 should be "normal"; and max x0 should
                         'be 255. We do not follow that convention.
                     CASE 3 '"P" Paint
                         y0 = TALLY(D$, ",")
                         FillColor = -1
                         RelativeOrAbs =0: x0 = ABS(x0)   'don't allow additive Paint colors
                         IF y0 = 5 THEN
                               Pcolor = RGB( VAL(PARSE$(D$, ",", 4)), VAL(PARSE$(D$, ",", 5)), VAL(PARSE$(D$, ",", 6)) )
                               FillColor = RGB( VAL(PARSE$(D$, ",", 1)), VAL(PARSE$(D$, ",", 2)), VAL(PARSE$(D$, ",", 3)) )
                         ELSEIF y0 > 0 THEN
                               IF x0 = RndNum THEN
                                   FillColor = RGB(RND(0,255), RND(0,255), RND(2,255))
                               ELSEIF x0 >=%TG_BLACK AND x0<= %TG_LIGHTWHITE THEN   'if < 0 or >15
                                   FillColor=tgColorVal (INT(x0))
                               ELSE
                                   FillColor = turtle.Color    '***NOTE THIS
                               END IF
                               C$=PARSE$(D$, ",", 2)
                               y0=ABS(VAL(C$))       'don't allow additive paint colors
                               IF y0=RndNum THEN
                                   PColor = RGB(RND(0,255), RND(0,255), RND(0,255))
                               ELSEIF y0>=%TG_BLACK AND y0<=%TG_LIGHTWHITE THEN
                                   PColor=tgColorVal( ABS(VAL(C$)))
                               ELSE
                                   PColor=turtle.Color       '***NOTE this default
                               END IF
                         ELSE
                             IF ABS(x0) = RndNum THEN
                                 FillColor = RGB(RND(0,255), RND(0,255), RND(2,255))
                              ELSE
                                 FillColor=tgColorVal (INT(x0))
                                 IF x0 <%TG_BLACK OR x0> %TG_LIGHTWHITE THEN FillColor = turtle.Color
                              END IF
                              Pcolor=turtle.Color
                         END IF
                         'paint color, border ... this follows PBDOS DRAW syntax;
                         'PBCC/PBWIN has more options, including fillstyle & STEP
                         IF FillColor < 0 THEN FillColor=turtle.Color
                         GRAPHIC PAINT BORDER (turtle.PX,turtle.PY), FillColor, Pcolor
                     CASE 4 '"M"  Move -- the DOS DRAW Mx,y (and M+x,-y) command
                         y0 = 0
                         comma = INSTR(D$,",")
                         IF comma = 0 THEN
                              'Assume error. Probably M had no X,Y suffix, & was a typo
                         ELSE
                             y0 = VAL(MID$(D$,comma+1))
                             IF RelativeOrAbs > 0 THEN      'if it's a relative move
                                 IF ABS(x0) = RndNum THEN x0 = RND(-10,10)
                                 IF ABS(y0) = RndNum THEN y0 = RND(-10,10)
                                 tgAddPos(x0, y0)       'scale & rotate, if needed, & call tgPlotter
                             ELSE
                                 'it's an absolute move, so don't rescale
                                 IF x0 = RndNum THEN x0 = RND(0,INT(turtle.canvaswidth))
                                 IF y0 = RndNum THEN y0 = RND(0,INT(turtle.canvasHeight))
                                 turtle.NX = x0
                                 turtle.NY = y0
                                 tgPlotter()
                             END IF
                         END IF
                  CASE ELSE
               END SELECT
                     'To execute the move, tgPlotter is called from tgAddPos
              ELSEIF cmd < 13 THEN
      
                       '#5-#12 are the 8 DOS BASIC moves
                       'They will be listed clockwise, starting at zero degrees
                       'Note: This assumes that the screen is not rescaled. 'Top' means Y=0.
      
                       IF x0 = 0 THEN x0 = 1
                       SELECT CASE cmd
                           CASE 5 '"R"  right, zero degrees, assuming no rotation
                               tgAddPos(x0, 0)       ' -- means "add X0 on X axis and 0 on Y"
      
                           CASE 6 '"F"    diagonally right & down (assuming top of window y=0)
                               tgAddPos(x0, x0)
      '
                           CASE 7 '"D"    down, 90 degrees
                               tgAddPos(0, x0)
      
                           CASE 8 '"G"   left & down
                               tgAddPos(-x0, x0)
      
                           CASE 9 '"L"   left or West or 180 degrees
                                tgAddPos(-x0, 0)
      
                           CASE 10 '"H"  left and up
                               tgAddPos(-x0,-x0)
      
                           CASE 11 '"U" up or North or 270 degrees
                               tgAddPos(0, -x0)
                           CASE 12 '"E" diagonally up and left
                               tgAddPos(x0,-x0)
      
                           CASE ELSE
                       END SELECT
              ELSEIF cmd = 13 THEN
                       '"A"  and TA -- DOS-DRAW degree of rotation
                       IF B$="T" THEN
                           'command "TA"... in PBDOS degrees can be -360 to 360
                           IF ABS(x0) = RndNum THEN x0 = RND(0,359)
                           IF RelativeOrAbs = %TG_FALSE THEN
                               turtle.HB = x0
                           ELSE
                               turtle.HB = turtle.HB + x0
                           END IF
                       ELSE
                           IF ABS(x0) = RndNum THEN x0 = RND(0,3)
      
                           IF x0 < 4 AND x0 >= 0 THEN
                               'in PBDOS A must be 0,1,2 or 3 (90 degree rotation)
                               IF RelativeOrAbs = %TG_FALSE THEN
                                   turtle.HB = x0*90  'set angle
                               ELSE
                                   turtle.HB = turtle.HB + x0*90
                               END IF
                           END IF
                       END IF
                       IF turtle.HB > 360 THEN
                          turtle.HB = turtle.HB -360
                       ELSEIF turtle.HB < -360 THEN
                          turtle.HB = turtle.HB +360
                       END IF
              ELSE
                  'These commands are not in DOS BASIC DRAW
                  'except that there was a very important X (for "execute") command in DRAW
                  'and tgDraw's Xn command amounts to the same thing, in function, if you have n = 1.
                  SELECT CASE cmd -13
                     CASE 1 '"I"
                         IF x0 = 0 THEN x0 = 1
                         tgBackward(x0)
                     CASE 2 '"J"
                         IF x0 = 0 THEN x0 = 1
                         tgForward(x0)         'move forward x0 (*scale factor) "steps"
                     CASE 3 '"K"  optionally, redefine Homing point; otherwise just go there
                         IF TALLY (D$, ",") THEN
                               x0 = VAL(PARSE$(D$, ",", 1))
                               y0 = VAL(PARSE$(D$, ",", 2))
                               IF RelativeOrAbs THEN
                                   turtle.HomeX = turtle.HomeX + x0
                                   turtle.HomeY = turtle.HomeY + y0
                               ELSE
                                   turtle.HomeX = x0
                                   turtle.HomeY = y0
                               END IF
                         END IF
                         tgHome
                     CASE 4 'O
                         IF ABS(x0) = RndNum THEN x0 = SGN(x0) * RND(0,359)
                         tgRight(x0)           'turn clockwise x0 degrees
                     CASE 5 '"Q[n...]"         'clear screen; optionally, set background & foregound color
                         'Note: Q by itself (with no n) will work, & sets background to default zero (black)
                         y0 = TALLY(D$, ",")
                         IF ABS(x0) = RndNum THEN
                              turtle.Background = RGB(RND(0,255), RND(0,255), RND(0,255))
                         ELSEIF y0 = 2 THEN
                               IF RelativeOrAbs =%TG_FALSE THEN
                                    turtle.Background = RGB( VAL(PARSE$(D$, ",", 1)), VAL(PARSE$(D$, ",", 2)), VAL(PARSE$(D$, ",", 3)) )
                               ELSE
                                    turtle.Background = RGB(CLNG(MyBackGround(1))+VAL(PARSE$(D$, ",", 1)), CLNG(MyBackGround(2))+VAL(PARSE$(D$, ",", 2)), CLNG (MyBackGround(3))+VAL(PARSE$(D$, ",", 3)))
                               END IF
                         ELSE
                               IF RelativeOrAbs = %TG_FALSE THEN
                                   turtle.Background = tgColorVal(INT(x0))
                               ELSE
                                  'what is current backround color?
                                  FOR K=%TG_BLACK TO %TG_LIGHTWHITE
                                      IF turtle.BackGround = tgColorVal(K) THEN
                                          y0 = (ABS(K + x0)) MOD 16    'incr color
                                          turtle.BackGround = (tgColorVal(INT(y0)))
                                          EXIT FOR
                                      END IF
                                  NEXT
                               END IF
                         END IF
                         tgSetColorRGB (turtle.Color, turtle.Background)
                         tgClearScreen()
                     CASE 6 '"V"
                         IF ABS(x0) = RndNum THEN x0 = SGN(x0) * RND(0,359)
                         tgLeft(x0)   'turn counter-clockwise x0 degrees
                     CASE 7 '"W"
                         IF ABS(x0) = RndNum THEN x0 = RND(1,10)
                         IF RelativeOrAbs = %TG_FALSE THEN
                             turtle.width = x0
                         ELSE
                             turtle.width = turtle.width + INT(x0)
                         END IF
                         IF turtle.width < 1 THEN
                             turtle.width = 1
                         ELSEIF turtle.width > 10 THEN
                             turtle.width = 10 'PB's max
                         END IF
                     CASE 8 'Xn  extends DOS eXecute command
                         'reserved as an alias for RPT (repeat)
                     CASE 9 '"Y"
                         'reserved
                     CASE 10 '"Z"
                         IF B$="N" THEN
                             SLEEP INT(x0)   'pause now, once only , X millisec
                         ELSE
                             turtle.pause = INT(x0) 'SLEEP millisec after each move
                             'NOTE: This way Zn just SETS sleep time; actual pause
                             'occurs only after the next move(s) -- in SUB tgPlotter
                         END IF
                     CASE 11 '? Graphic Print... Must be the last command in Dr$
                          D$=MID$(Dr$,I+1)
                          tgPrint(D$)
                          tgUpdateScreen
                          EXIT SUB
                     CASE 12 '* TextDraw ... Must be the last command in Dr$
                          'FUNCTION tgDrawCheck deletes the * and calls tgTextDrawCode
                         ' so CASE #12 should not occur
                     CASE 13 '! STDOUT Must be last command in Dr$
                         D$=MID$(Dr$,I+1)
                         STDOUT D$
                         SLEEP 10
                         EXIT SUB
                     CASE 14 '/
                         IF x0 >=0 AND x0 < 5 THEN
                             turtle.linestyle = INT(x0)
                         ELSE
                             turtle.linestyle = 0   'solid line
                         END IF
                     CASE 15 '$ SAVESCREEN to a .bmp file
                         CALL tgSaveScreen
                         SLEEP 500
                     CASE 16 '# RESET
                         tgSetDefaults
                     CASE 17 '& REFRESH
                         tgUpdateScreen
                     CASE 18 ' @ RANDSET
                         IF INSTR (D$, ",") THEN
                           turtle.LoRandom = VAL(PARSE$(D$, ",", 1))
                           turtle.HiRandom = VAL(PARSE$(D$, ",", 2))
                           IF turtle.HiRandom < turtle.LoRandom THEN
                               y0 = turtle.LoRandom: z0=turtle.HiRandom
                               turtle.LoRandom = z0: turtle.HiRandom = y0
                           END IF
                         ELSE
                           'use defaults for each variable
                           turtle.LoRandom = 0
                           turtle.HiRandom = 0
                         END IF
                     CASE 19 ' ~ size & style (for ? statement)
                         IF INSTR(D$, ",") THEN y0 = VAL(PARSE$(D$, ",", 2)) ELSE y0 = turtle.FontStyle
                         GRAPHIC FONT TRIM$(turtle.FontName), INT(x0), INT(y0)
                         turtle.FontPoints = INT(x0)
                         turtle.FontStyle = y0
                     CASE 20 '^ show turtle's current direction
                             'an alternative command is ARROW, which is translated into ^
                         tgDraw Arrow
                     CASE 21 '> dist between 2 points at which program will switch from using
                             ' DRAW Mx,y to to using DRAW Bm,y -- when user is "drawing" w/ mouse
                         turtle.DistGap = x0
                 END SELECT
            END IF
         RETURN
      END SUB
      
      'read a .bmp pic file or a file that contains tgDraw strings, & send
      'each non-REM'd line to tgDraw for processing
      SUB tgReadFile(FileNam$)
          LOCAL A AS STRING
          LOCAL FF, AA, L, R, chain AS LONG
          LOCAL X,Y AS SINGLE
          LOCAL File AS STRING
          LOCAL hBmp AS DWORD
          File$= Filenam$
      
          File$ = UCASE$(TRIM$(File$))
          IF INSTR(File$,"READFILE") = 1 THEN
              File$ = MID$(File$, 9)
          END IF
          IF INSTR(File$,CHR$(34)) > 0 THEN
             REPLACE CHR$(34) WITH "" IN File$
          END IF
          File$=TRIM$(File$)
      DO
          chain = 0
          IF DIR$(File$) = "" THEN
              STDOUT File$ + " not found"
              EXIT SUB
          END IF
      
          IF RIGHT$(File$,4) = ".BMP" THEN   'if it's a picture, load it & show it
      
              GRAPHIC RENDER File$, (0,0)-(turtle.canvaswidth -1, turtle.canvasheight -1)
      
              #IF 0
              'this is an alternative way of loading; it is safe to delete it
              GRAPHIC BITMAP LOAD File$, INT(turtle.canvaswidth), INT(turtle.canvasheight) TO hBmp
              GRAPHIC COPY hBmp, 0& TO (0, 0)
              'delete bitmap & reattach to current graphic window
              GRAPHIC ATTACH hBmp, 0&
              GRAPHIC BITMAP END
              IF turtle.doubleBuffer = %TG_TRUE THEN
                  GRAPHIC ATTACH turtle.AttachGraphicHandle, 0&, REDRAW
              ELSE
                  GRAPHIC ATTACH turtle.AttachGraphicHandle, 0&
              END IF
              #ENDIF
      
              SLEEP 500
              tgUpdateScreen
              EXIT SUB
          END IF
      
          FF = FREEFILE
          OPEN File$ FOR INPUT AS #FF
         'better hope it's a tgDraw script
          LINE INPUT #FF, A$
          A$=UCASE$(A$)
          L = INSTR(A$, "TGD")
          IF L < 1 or L > 2 THEN
              STDOUT "   "+ File$ + " is not a valid tgDraw script file"
      '       first line should start with 'TGD or TGD
              CLOSE #FF
              EXIT SUB
          END IF
      
          DO WHILE NOT EOF (FF)
              LINE INPUT #FF, A$
              A$=TRIM$(A$)
              L=LEN(A$)
              IF L > 1 THEN
                  'take '?' to signify PRINT text rather than process DRAW code
                  ' * signifies TextDraw, as opposed to command code
                  ' ! signifies STDOUT the rest of the line
                  IF INSTR(A$,ANY "?*!") <1 THEN
                      A$=UCASE$(A$)
                  END IF
              END IF
              IF L > 0 THEN
                  IF INSTR(A$,"'") <> 1 THEN     'exclude REM'd-out lines
                      'chain from this file to another one?
                      AA=INSTR(TRIM$(UCASE$(A$)),"READFILE")
                      IF AA > 0 AND AA < 4 THEN
                          A$=MID$(A$,AA+9)
                          AA =INSTR(A$, ANY CHR$(32)+CHR$(34))
                          IF AA AND LEN (A$)>AA THEN
                              REPLACE CHR$(32) WITH "" IN A$
                              REPLACE CHR$(34) WITH "" IN A$
                          END IF
                          IF RIGHT$(A$,4) = ".BMP" THEN   'if it's a picture, show it
                              GRAPHIC RENDER A$, (0,0)-(turtle.canvaswidth,turtle.canvasheight)
                              tgUpdateScreen
                              SLEEP 1000
                              ITERATE DO
                          ELSE
                              chain = -1
                              file$ = A$
                              EXIT DO
                          END IF
                      END IF
                      IF UCASE$(A$) = "QUIT" THEN
                          EXIT DO
                      END IF
                      AA=INSTR(A$,"DRAW")
                      IF AA >0 AND AA < 4 THEN
                          'Could check also for line numbers, but here we don't.
                          'For that matter, a "SCREEN" statement in an old .BAS file would be
                          'interpreted by tgDraw as setting S(scale) & C(color) & jumping R1 & E2.
                          A$ = MID$(A$, AA+5)
                          IF INSTR(A$,CHR$(34)) > 0 THEN
                              REPLACE CHR$(34) WITH "" IN A$
                          END IF
                          R = INSTR(A$,"'")       'exclude REM's that follow command
                          IF R > 1 THEN A$ = LEFT$(A$,R-1)
                      END IF
                      CALL tgDraw (A$)
                  END IF
                  'SLEEP 1000  'or in file use turtle.pause -- see tgDraw command Zn
              END IF
              DoneReadin:
          LOOP
          CLOSE #FF
        LOOP UNTIL chain = 0
      END SUB
      
      SUB tgSaveScreen()           'graphics screen
          LOCAL A,B,F AS STRING
          LOCAL I, N AS LONG
          f$ = "TGD"          'note that no extension is used in file name
          A$=DIR$(f$+"*.BMP")
          WHILE A$<>""
              I=VAL(MID$(A$,4))
              IF I>N THEN N=I
              A$=DIR$
          WEND
          I=VAL(MID$(A$,4))
          IF I>N THEN N=I
      
          B$="00"+TRIM$(STR$(N+1))
          B$=RIGHT$(B$,3)
          A$=f$+B$+".BMP"
          GRAPHIC SAVE A$
          STDOUT "Saving screen to file " + A$
          SLEEP 50
      END SUB
      
      SUB tgHelpOnDraw
        LOCAL A AS STRING, I AS INTEGER
      
        A$=STRING$(80,"=")
      
        'This file is for PBCC print to console. For PBWin use msgbox
        #IF %DEF(%PB_CC32)
        STDOUT A$
        MID$(A$,10) = "Turtle Variables & Current Settings"
        STDOUT A$
        STDOUT "TYPE TurtleType ' a GLOBAL variable"
        STDOUT "    ID AS LONG     'unique identifier (for multiple turtles)      "+FORMAT$(turtle.ID)     
        STDOUT "    HB AS EXT       'heading BASE angle of turtle, in degrees  "+FORMAT$(turtle.HB)
        STDOUT "    H AS EXT        'heading angle of turtle, in degrees       "+FORMAT$(turtle.H)
        STDOUT "    PS AS LONG      'PenStatus down (to draw) or up            "+FORMAT$(turtle.PS)
        STDOUT "   RTS AS LONG      '0 or -1. -1=Return to start after a jump. See 'NJ' command "+FORMAT$(turtle.RTS)
        STDOUT "    PX AS SINGLE    'present location, X axis                  "+FORMAT$(turtle.PX)
        STDOUT "    PY AS SINGLE    'present location, Y axis                  "+FORMAT$(turtle.PY)
        STDOUT "    NX AS SINGLE    'new location, X axis                      "+FORMAT$(turtle.NX)
        STDOUT "    NY AS SINGLE    'new location, Y axis                      "+FORMAT$(turtle.NY)
        STDOUT " DistGap AS SINGLE  'When User draws with a mouse              " + FORMAT$(turtle.DistGap)
        STDOUT "                    'how far apart (in pixels) must 2 points be before turtle"
        STDOUT "                    'moves without plotting? cf DRAW BMx,y versus DRAW Mx,y
        STDOUT " Color AS LONG      'foreground color for draw                 "+FORMAT$(turtle.COLOR)
        STDOUT " Background AS LONG 'background color                          "+FORMAT$(turtle.Background)
        STDOUT " Width AS SINGLE    'pen width in pixels, or window units      "+FORMAT$(turtle.WIDTH)
        STDOUT " LineStyle AS LONG  '0=Solid line;1=Dash;2=Dot;3=DashDot;4=DashDotDot "+FORMAT$(turtle.LINESTYLE)
        STDOUT "  'LineStyle > 0 requires that Width = 1. See PBCC/PBWin GRAPHIC STYLE"
        STDOUT " Pause AS LONG      'millisec SLEEP after EACH pen move+draw   "+FORMAT$(turtle.PAUSE)
        STDOUT "                    'zero sleep is OK"
        STDOUT " Scale AS SINGLE    'multiply all move-sizes by this value     "+FORMAT$(turtle.SCALE)
        STDOUT " kee AS LONG        'mouse click or keypress                   "+FORMAT$(turtle.kee)
        STDOUT " DoubleBuffer AS BYTE   '0=singleBuffer                        "+FORMAT$(turtle.doubleBuffer)
        STDOUT " AttachGraphicHandle as DWORD   'PB handle for graphic window  "+FORMAT$(turtle.AttachGraphicHandle)
      
        STDOUT " CanvasWidth  AS LONG  'size of current turtle window          "+FORMAT$(turtle.canvaswidth)
        STDOUT " CanvasHeight AS LONG  'size of current turtle window          "+FORMAT$(turtle.canvasheight)
        STDOUT " HomeX AS SINGLE       'redefinable place to return to...      "+FORMAT$(turtle.HomeX)
        STDOUT " HomeY AS SINGLE       'See tgHome (K) command & tgSetDefaults "+FORMAT$(turtle.HomeY)
        STDOUT " LoRandom AS LONG      'Set range of vals for random numbers..."+FORMAT$(turtle.LoRandom)
        STDOUT " HiRandom AS LONG      '...See RANDSET (alias @)               "+FORMAT$(turtle.HiRandom)
        STDOUT " Font for GRAPHIC PRINT with ? statement                       "+turtle.FontName
        STDOUT " Font size (points) for GRAPHIC PRINT with ? statement         "+FORMAT$ (turtle.FontPoints)
        STDOUT " Font Style 0=normal 1=bold 2=italics 4=underline 8=strikeout  "+FORMAT$(turtle.FontStyle)
      
      STDOUT "END TYPE"
      STDOUT ""
      
      
        MID$(A$,10) = " HELP on tgDraw Commands =========="
        STDOUT A$
        STDOUT " Syntax:  tgDraw stringexpression$  "
        STDOUT "    stringexpression$  Contains one or more drawing commands;"
        STDOUT "    it may include variables (e.g., STR$(X))as well as literals"
        STDOUT "    except when it is used in a batch-type text file "
        STDOUT "    or in a compiled program such as tgDrawer.EXE."
        STDOUT "    No need for old DOS VARPTR$ or the X ('execute') command"
        STDOUT "    Try (e.g.) this: tgDraw ( A$ + B$ + FORMAT$(LOG(x)))
        STDOUT""
        STDOUT " Optional Prefixes for any of the Drawing and Movement Commands "
        STDOUT "      B          Move without plotting (turtle pen status = up) "
        STDOUT "      N          Plot, then return to starting point"
        STDOUT""
        STDOUT " DOS-style DRAW Line-Drawing and Cursor-Movement Commands, "
        STDOUT " listed clockwise, starting at 0 degrees, in PBDOS convention."
        STDOUT " Directions here assume that A or TA rotation = 0.
        STDOUT "      Rn           Right or East n units"
        STDOUT "      Fn           Diagonally down n units and right n units"
        STDOUT "      Dn           Down or South"
        STDOUT "      Gn           Diagonally down n units and left n units"
        STDOUT "      Ln           Left or West "
        STDOUT "      Hn           Diagonally up n units and left n units"
        STDOUT "      Un           Up or North  "
        STDOUT "      En           Diagonally up n units and right n units"
        STDOUT "      M[+-]x,y     Move to point x,y...Use + - for relative moves."
        STDOUT "                   Size of relative moves also depends on Scale: see Sn"
        STDOUT""
        STDOUT " DOS-style DRAW Color, Scale, and Rotation Commands"
        STDOUT "      C[+-]n[,G,B] Change the turtle's pen color.  If only one number is given,
        STDOUT "            a DOS color (0-15) is used. See below for more on Colors.
        STDOUT "      Pp,b         Fill enclosed shape that has border color 'b' with color 'p'"
        STDOUT "                   RedGreenBlue values can also be used: Pn1,n2,n3,n4,n5,n6
        STDOUT "      S[+-]n       Scale: set length of moves "
        STDOUT "      A[+-]n      Set Angle n * 90 degrees. N must be 0, 1, 2, or 3"
        STDOUT "      TA[+-]n   Set Angle to n degrees (-360 to +360)"
        STDOUT "                NOTE: Use + or - only to make TA & A angles additive like Turtle O & V "
        STDOUT""
        STDOUT " New tgDraw Commands"
        STDOUT "      In       Jump backward n units at present angle or turtle heading "
        STDOUT "      Jn       Jump forward  n units at present angle or turtle heading "
        STDOUT "      K[+x,+y] Home -- move to [optional, new] x,y, set heading to 0, pendown"
        STDOUT "               Enter x,y to define a new Home Base. # or 'RESET' will restore default"
        STDOUT "      On       Turn right (clockwise) n degrees"
        STDOUT "      Vn       Turn left (counterclockwise) n degrees"
        STDOUT "      W[+-]n   Set turtle pen Width to n units. Must be 1-10, & 1 for LineStyle > 0 "
        STDOUT "      /n       LineStyle 0=solid (default); 1=dash; 2=Dot; 3=DashDot 4=DashDotDot
        STDOUT "      Xn(A$)   Shorthand for RPT [if n=1, this amounts to DOS-DRAW's X]"
        STDOUT "    RPTn(A$)   Repeat n times any tgDraw string that is within parentheses"
        STDOUT "               Multiple RPTs are OK, and they may be nested
        STDOUT
        STDOUT "      Q[+-][n,G,B] Clear Screen [with optional new background color]; then Home"
        STDOUT "      Zn     SLEEP n millisec after each move. Use N prefix for a 1-time pause"
        STDOUT "      ?      GRAPHIC PRINT (Windows font) everything on a line that follows the '?'"
        STDOUT "               Note: You can print at any angle set with A or TA, and any size.
        STDOUT "      ~n1,n2 or FONTn1,n2  Set size (in points) & style for GRAPHIC PRINT"
        STDOUT "              style 0=normal 1=bold 2=italic 4=underline 8=strikeout & 3=1+2, etc."
        STDOUT "      FONTNAME A$ Set GRAPHIC PRINT font to e.g., Courier, Helvetica"
        STDOUT "      *      TextDraw the rest of the line "
        STDOUT "      !      Output the rest of the line to STDOUT -- i.e., Console or MsgBox"
        STDOUT "      >n     or 'DISTGAP'n . Move but do not draw a line if 2 mouse-drawn x/y
        STDOUT "             locations exceed this distance in pixels. Cf DRAW BMx,y versus Mx,y"
        STDOUT "      $      or 'SAVESCREEN' Save graphics screen to a .BMP file"
        STDOUT "      #      or 'RESET'   Reset all Turtle defaults (but not colors)"
        STDOUT "      &      or 'REFRESH' Update graphics screen"
        STDOUT "      666    or 'RANDOM'  Change n to a random value --"
        STDOUT "             Applies only to M,BM,C,Q,A,TA,S,W. If RANDSET is used, the values"
        STDOUT "             will be in the same range for ALL of the above variables;"
        STDOUT "             otherwise ranges will be adjusted differently for each variable"
        STDOUT "      @n1,n2 or 'RANDSET'[n1,n2] Set Lo/Hi range of values for ALL randoms"
        STDOUT " READFILEa$  From a script file, display a .BMP pic or chain to another script"
        STDOUT "             NOTE: do not include any other commands on the same line"
        STDOUT ""
        STDOUT " And to enter tgDraw commands 'on the fly', from the keyboard,
        STDOUT " or a drawing program that records freehand mouse moves & clicks,
        STDOUT " & translates them into DRAW code, see TGDRAWER.BAS."
        STDOUT
        FOR I = 1 TO 15
            LOCATE , I * 3 + 1
            COLOR I
            IF I < 10 THEN STDOUT "0";
            STDOUT LTRIM$(STR$(I));
        NEXT
        STDOUT " (colors... 0=black)";
        STDOUT
        STDOUT "     Note: Graphics colors can be customized by editing SUB tgColorVal()"
        'STDOUT "     So graphic colors might be different from those shown here on the console screen"
        STDOUT "     Note 2: RedGreenBlue (RGB) values 0-255 as well as DOS (0-16) colors may be used"
        STDOUT "     E.g., C255,255,255 = C15 = LIGHTWHITE. This holds for P & Q commands too.
        A$=STRING$(80,"=")
        MID$(A$,30)=" End of tgDraw Help "
        STDOUT A$
      
        #ENDIF
      END SUB
      
      
      '===============================================================================
      '=                      Basic implementation of L-System                       =
      '=                            Petr Schreiber, 2008                             =
      '=                                                                             =
      '=                                v0.1 PREVIEW                                 =
      '===============================================================================
      
      TYPE tReplace
        symbol AS STRING * 1      ' -- Symbol to replace
        changesTo AS STRING * 255 ' -- With what replace ( dynamic string would be better here )
      END TYPE
      
      SUB LSystem_Init( VariablesNum AS LONG )
      
        ' -- Storage for table of what replace with what
        DIM LSystem_Table(VariablesNum) AS GLOBAL tReplace
        GLOBAL LSystem_Solution AS STRING
      
      END SUB
      
      SUB LSystem_FillPair( id AS LONG, SOURCE AS STRING, destination AS STRING )
      
        LSystem_Table(id).symbol        = SOURCE
        LSystem_Table(id).changesTo     = destination
      
      END SUB
      
      SUB LSystem_Solve( recipe AS STRING, iterations AS LONG )
      
        ' i = iterator, s = symbol, n = nth character
        LOCAL i, s, n AS LONG
        LOCAL char AS STRING
      
        LSystem_Solution = recipe
      
        FOR i = 1 TO iterations
          FOR s = 1 TO UBOUND(LSystem_Table)          ' -- For each symbol/variable
      
            n = 0
            WHILE n <= LEN(LSystem_Solution)
      
              INCR n
              char = MID$(LSystem_Solution, n, 1)
      
              IF char = "(" THEN                      ' -- Already replaced by other symbol
                n = INSTR(n, LSystem_Solution, ")")   ' -- Seek where it ends
                IF n = LEN(LSystem_Solution) THEN
                  EXIT LOOP                           ' -- Last character
                ELSE
                  ITERATE LOOP                        ' -- Not last, journey continues
                END IF
              END IF
      
              ' -- We found a match for symbol, lets "replace" it
              IF char = LSystem_Table(s).symbol THEN
      
                LSystem_Solution = STRDELETE$(LSystem_Solution, n, 1)
                LSystem_Solution = STRINSERT$(LSystem_Solution, "("+LSystem_Table(s).changesTo+")", n)
                n = INSTR(n, LSystem_Solution, ")")
      
              END IF
      
            WEND
          NEXT
          LSystem_Solution = REMOVE$(LSystem_Solution, ANY "()")
      
        NEXT
      
      
        FOR n = 1 TO LEN(LSystem_Solution)
      
          char  = MID$(LSystem_Solution, n, 1)
          SELECT CASE char
            CASE "A", "B"                 ' -- Both A, B tokens mean draw line
              tgForward (3)
      
            CASE "+"                      ' -- Clockwise 60°
              tgLeft (-60)
      
            CASE "-"                      ' -- Counter-Clockwise 60°
              tgRight (-60)
      
          END SELECT
      
        NEXT
      
      END SUB
      
      '********** from textrotate.bas, PowerBASIC (PBCC) Sample programs **********************************************************
      'requires Win32API
      FUNCTION MakeRotatedFont (BYVAL hDC AS DWORD, BYVAL FontName AS STRING, _
                                BYVAL PointSize AS LONG, BYVAL Angle AS LONG, _
                                BYVAL fBold AS LONG, BYVAL fItalic AS LONG, _
                                BYVAL fUnderline AS LONG, BYVAL fStrikeThru AS LONG) AS DWORD
      '--------------------------------------------------------------------
      ' Create a rotated font. Angle is 1/10 of degrees, so 900 = 90 degrees.
      ' Uses EnumCharSet enumeration to get correct character set.
      '--------------------------------------------------------------------
      
        LOCAL CharSet AS LONG
      
        PointSize = 0 - (PointSize * GetDeviceCaps(hDC, %LOGPIXELSY)) \ 72
        EnumFontFamilies hDC, BYVAL STRPTR(FontName), CODEPTR(EnumCharSet), BYVAL VARPTR(CharSet)
      
        FUNCTION = CreateFont(PointSize, 0, _  'height, width (default=0)
                   Angle, Angle, _             'escapement(angle), orientation
                   fBold, _                    'weight (%FW_DONTCARE = 0, %FW_NORMAL = 400, %FW_BOLD = 700)
                   fItalic, _                  'Italic (1/0)
                   fUnderline, _               'Underline (1/0)
                   fStrikeThru, _              'StrikeThru (1/0)
                   CharSet, %OUT_TT_PRECIS, _
                   %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, _
                   %FF_DONTCARE , BYCOPY FontName)
      
      END FUNCTION
      '====================================================================
      FUNCTION EnumCharSet (elf AS ENUMLOGFONT, ntm AS NEWTEXTMETRIC, _
                            BYVAL FontType AS LONG, CharSet AS LONG) AS LONG
        CharSet = elf.elfLogFont.lfCharSet
      END FUNCTION

      Code:
      'TGD or TGDRAWER.BAS
      'A demo for tgDraw.INC
      'by Emil Menzel, 2008. revised 2009 for PBCC 5.01
      'must be compiled in PBCC. It uses both CONSOLE & graphics screens.
      'Purpose: Allow user to type in Turtle & DRAW Graphics commands on the fly,
      'or draw with a mouse, or call up & run files containing tgDraw scripts.
      'I.e., this is a simple interpreter.
      
      #BREAK ON      'unrem this, if you use tgDrawer as a standalone program... See also PBMain function name
      #DEBUG DISPLAY ON
      #IF NOT %DEF(%WINAPI)
          #INCLUDE "WIN32API.INC"
      #ENDIF
      #INCLUDE ONCE "tgDraw.INC"
      
      TYPE User
          X AS SINGLE
          Y AS SINGLE
          LB AS LONG
          RB AS LONG
          Kee AS DWORD
          Done AS LONG
          Finished AS LONG
      END TYPE
      
      GLOBAL GraphicWindowChildOldProc AS LONG
      GLOBAL U AS User
      
      'name this function PBMain if you want to use tgDraw as a standalone program,
      'or delete it or name it (e.g.) PBMainXXX otherwise
      FUNCTION PBMAIN() AS LONG
          LOCAL A AS STRING
          A = "Draw on graphics screen with mouse. Type tgDraw commands on console. Help=F1. Quit=Esc."
          tgDrawer (A)
      END FUNCTION
      
      
      ' Called whenever keyboard or mouse activity is detected in the graphics window.
      '(Mark Hunter's simplification of Steve Rossel's mouse & keyboard routine)
      FUNCTION GraphicWindowChildNewProc(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
        LOCAL L AS LONG
        SELECT CASE wMsg
           '''CASE %WM_CHAR
             '''stdout chr$(LO(WORD,wParam));
      
           CASE %WM_NCHITTEST
           CASE %WM_MOUSEMOVE
             U.x = LO(WORD, lParam)  ' Current mouse X Position in the graphic window.
             U.y = HI(WORD, lParam)  ' Current mouse Y Position in the graphic window.
           CASE %WM_LBUTTONDOWN
              U.LB =1
           CASE %WM_LBUTTONUP
              U.LB = 0
           CASE %WM_RBUTTONDOWN
              U.RB = 1
           CASE %WM_RBUTTONUP
              U.RB = 0
           CASE %WM_KEYDOWN
              U.kee = wparam
           CASE %WM_KEYUP
              U.kee = 0
        END SELECT
      
        FUNCTION = CallWindowProc(GraphicWindowChildOldProc, hWnd, wMsg, wParam, lParam)
      END FUNCTION
      
      
      FUNCTION tgDrawer(Message AS STRING) AS LONG
      
        LOCAL hGraphicWindow AS DWORD, pid AS LONG
        LOCAL hStatic AS DWORD, hwin AS DWORD
        LOCAL A,AA AS STRING
        LOCAL I,J,K,L, c, f, row,col,maxRow,maxCol, xx AS LONG
        LOCAL cmd, cmdUC, m1, m2 AS STRING
        LOCAL LastX, LastY, Dist AS SINGLE
        LOCAL Pt AS PointAPI
      
        GRAPHIC WINDOW "tgDrawer ", 0, 0, 639, 479 TO hGraphicWindow
      
        tgAttachGraphic(hGraphicWindow, 0, %TG_DOUBLE_BUFFER)
      
        ' Retrieve handle to static control (the graphic) on the graphic window (dialog box).
        hStatic = GetWindow(hGraphicWindow, %GW_CHILD)
      
        ' Subclass the graphic window; any keyboard or mouse activity in the window
        ' will cause the GraphicWindowChildNewProc function to be called.
        GraphicWindowChildOldProc = SetWindowLong(hStatic, %GWL_WNDPROC, CODEPTR(GraphicWindowChildNewProc))
      
        maxRow=200: MaxCol=90   'for virtual screen
        CONSOLE SET LOC 0,510
        CONSOLE SET SCREEN 10,MaxCol
        CONSOLE SET VIRTUAL MaxRow, MaxCol
        turtle.background = %BLACK
        turtle.color = %WHITE
        m1$ = "#### "
        m2$ = "####.# "
        tgClearScreen     'centers the cursor
        IF Message$<> "" THEN
            GRAPHIC TEXT SIZE Message$ TO lastX, lastY
            Dist = ABS((turtle.CanvasWidth - lastX) \2)
            tgDraw "BM"+FORMAT$(INT(Dist))+ ","+FORMAT$(INT(turtle.canvasheight/2)) + "?"+Message$
        END IF
        tgUpdateScreen
        LastX =0: LastY = 0
        MOUSE 7, DOWN, DOUBLE, UP     'this is mouse on console, not graphics screen
        MOUSE ON
        CURSOR ON, 50
        ' Loop until Esc is pressed on either the graphic window or the console
        WHILE U.finished = 0
          IF U.Done = 59 THEN
              A$ = CHR$(0) + CHR$(59)   'F1 was pressed on graphics screen
              U.Done = 0
          ELSE
              'NOTE: this assumes keypress on graphics screen & on console will be treated the same
              'But of course, knowing U.kee, you can still tell the dfference, if needed
              IF U.kee THEN
                  GRAPHIC INKEY$ TO A$  'keydown of Graphics screen
              ELSE
                  A$ = INKEY$           'key press on console
              END IF
          END IF
          L = LEN(A$)
          IF L=4 THEN
              K = ASC(A$,3)              'see Keybdcode.bas in PBCC samples
              IF K = 4 OR K=2 THEN
                  LOCATE MOUSEY, MOUSEX  'mouse click on console. Move text cursor.
              END IF
              IF K =2 THEN A$=CHR$(13)ELSE A$="" : 'assume double-click = ENTER
          END IF
          IF L THEN row = CURSORY: col = CURSORX
          SELECT CASE A$
             CASE ""                     'nothing
             CASE CHR$(0)+CHR$(75)       'left arrow
                 IF col > 1 THEN LOCATE , col-1
             CASE CHR$(0)+CHR$(77)       'right arrow
                 IF col < MaxCol THEN LOCATE , col+1
             CASE CHR$(0)+CHR$(72)       'up arrow
                 IF row > 1 THEN LOCATE row-1
             CASE CHR$(0)+CHR$(80)       'down arrow
                 IF row < MaxRow THEN LOCATE row+1
             CASE CHR$(0)+CHR$(71)       'home
                 LOCATE ,1
             CASE CHR$(0)+CHR$(79)       'end
                 LOCATE ,MaxCol
             CASE CHR$(0)+CHR$(59)       'F1   help
                 IF PAGEACTIVE = 1 THEN
                     PAGE 2
                     CLS
                     STDOUT ""
                     STDOUT "Help on tgDrawer (the current program):"
                     STDOUT
                     STDOUT "To start drawing with mouse, left-click on Graphics screen "
                     STDOUT "Left- or right-click will also relocate the Turtle"
                     STDOUT ""
                     STDOUT "To type in commands, type on either Graphics or Console Screen"
                     STDOUT "To block commands in a line, insert an ' (apostrophe) before them"
                     STDOUT "Double-click a console line (or press Enter) to execute all commands on line"
                     STDOUT "Press F1 for help"
                     STDOUT "      F2 list the .TXT files in directory"
                     STDOUT "      F3 list the .BMP files in directory"
                     STDOUT "      F4 run Notepad.exe"
                     STDOUT "      F5 run MsPaint.exe"
                     STDOUT "      F6 SHELL to DOS prompt"
                     STDOUT "      F7 Color chart"
                     STDOUT "      Ctrl-C copy (& Trim) current console line to clipboard"
                     STDOUT "      Ctrl-D change COLOR to that at current mouse x,y location"
                     STDOUT "      Ctrl-X & Ctrl-Y to copy (no Trim) current line AND erase it"
                     STDOUT "      Esc to quit help &/or current program"
                     STDOUT "To GOTO any given console page (1-8), row, & col, Type PAGE n1,n2,n3"
                     STDOUT ""
                     STDOUT "(NOTE: In tgDrawer as in tgDraw script files, use only string literals)"
                     STDOUT "To load a .BMP file or run a tgDraw script, type its name & press Enter"
                     STDOUT "To read, edit or copy from a tgDraw script file: use (e.g.) Notepad"
                     STDOUT "To paste in commands that you have copied into clipboard, press Ctrl-V"
                     STDOUT "For additional Edit commands, click top-left corner of Console Screen"
                     STDOUT ""
                     STDOUT "To quit tgDrawer, press Esc from Pg 1 of Console Screen"
                     STDOUT ""
                     CALL tgHelpOnDraw
      
                     PAGE 2,2
                     LOCATE 1,1
                 ELSE
                     PAGE 1,1
                 END IF
      
              CASE CHR$(0)+CHR$(60), CHR$(0)+CHR$(61)   'F2, F3 show .TXT & .BMP files in current Directory
                 DIM temp$
                 IF A$=CHR$(0)+CHR$(60) THEN temp$=DIR$("*.TXT") ELSE temp$=DIR$("*.BMP")
                 IF temp$<>"" THEN STDOUT: STDOUT "files in current directory"
                 WHILE LEN(temp$)
                    STDOUT UCASE$(temp$)
                    temp$ = DIR$
                 WEND
      
              CASE CHR$(0) + CHR$(62)    'F4 shell to Notepad
                  pid=SHELL ("NOTEPAD.EXE",1)   'run asynchronously, same time as TGD
              CASE CHR$(0) + CHR$(63)    'F5 shell to MsPaint
                  pid=SHELL ("MSPAINT.EXE",1)   'run asynchronously, same time as TGD
              CASE CHR$(0) + CHR$(64)     'F6 SHELL to command line
                  STDOUT ""
                  STDOUT "When done with DOS prompt, Type EXIT"
                  STDOUT ""
                  SHELL ENVIRON$("COMSPEC")
              CASE CHR$(0)+CHR$(65)      'F7 Color chart
                  tgDraw "Q"                                'clear the graphics screen
                  tgDraw "C15 S1"                       'color, and scale for line drawing
                  tgDraw "BM240,130 U80R80 D80L80"  'draw big box
                  tgDraw "FONT 8,1 BM230,137  ?To get a Random color
                  tgDraw "BM230,150 ?Click in box & type: Prandom , 15
                  tgDraw "BM0,220"
                  tgDraw "X16(BM+31,+0 U40R20D40L20)"  'draw a row of 16 small box white boxes
                  tgDraw "BM0,220 C0"
                  tgDraw  "X16 (BM+31,+0 BE3 P16,15 BG3 C+1 )"  'paint each box. If  P val >15=it is changed to C
                  tgDraw "BM31,230 C15 ? 0        1        2        3         4        5        6         7        8        9        10       11       12      13       14      15
                  tgDraw "BM230,245 FONT8,1 ?To make pen the same color as Mouse's location, press Ctrl+d
                  tgDraw "BM230,260 ?Or type Cn or Cn1,n2,n3
      
              CASE CHR$(27)              'Esc
                  IF PAGEACTIVE = 1 THEN
                      U.finished = 1
                  ELSE
                      PAGE 1, 1
                  END IF
              CASE CHR$(13)              'Enter. Process below.
                  U.Done = 1
              CASE CHR$(8)               'backspace
                  IF col > 1 THEN
                      LOCATE , col-1
                      STDOUT SPACE$(1);
                      LOCATE , col - 1
                  END IF
              CASE CHR$(3),CHR$(24),CHR$(25)  'Ctrl-C, Ctrl-X, Ctrl-Y copy entire current line to clipbd
                                              'X & Y will then erase current, visible line
                  AA$=SPACE$(MaxCol)
                  FOR J = 1 TO MaxCol
                      MID$(AA$,J,1) = CHR$(SCREEN(Row,J))
                  NEXT
                  IF A$ = CHR$(3) THEN AA$=LTRIM$(AA$)    'delete leading spaces
                  CLIPBOARD RESET
                  CLIPBOARD SET TEXT(AA$)
                  IF A$ > CHR$(3) THEN
                      LOCATE ,1: STDOUT SPACE$(MaxCol);
                      LOCATE ,1
                  END IF
              CASE CHR$(4)               'Ctrl-D set color to whatever RGB color the mouse is on
                  GRAPHIC GET PIXEL (U.X, U.Y) TO turtle.Color
              CASE CHR$(22)              'Ctrl-V Paste from Clipboard
                 CLIPBOARD GET TEXT TO AA$
                 STDOUT AA$;
                 '''U.Done = 1   'execute immediately
              CASE < CHR$(32)
                  '''stdout "you pressed ASC "+str$(ASC(A$))
              CASE > CHR$(31)
                 IF L =1 THEN
                     STDOUT A$;
                 END IF
          END SELECT
      
          IF U.Done = 1 THEN
              'read whatever line the console cursor is on
              cmd=""
              FOR I = 1 TO MaxCol
                  B$ = CHR$(SCREEN(Row,I))
                  IF B$ = "'" THEN EXIT FOR     'exclude REMs
                  cmd = cmd + B$
              NEXT
              cmd=TRIM$(cmd)
              cmdUC=UCASE$(cmd)
              IF LEN(cmd) > 4 THEN A$ = UCASE$(RIGHT$(cmd,4))
              IF LEN(cmd) < 1 THEN
                  'skip it
      
              ELSEIF INSTR (cmdUC, "SHELL") = 1 THEN
                  STDOUT ""
                  STDOUT "When done with DOS prompt, Type EXIT"
                  STDOUT ""
                  IF LEN (cmd)> 5 THEN
                      SHELL ENVIRON$("COMSPEC") + " \c "+ MID$(cmd,6)
                  ELSE
                      SHELL ENVIRON$("COMSPEC")
                  END IF
              ELSEIF INSTR (cmdUC, "READFILE") = 1 OR A$ = ".TXT" OR A$ = ".BMP" THEN
                  'this assumes .txt files are tgDraw commands
                  'To read plain vanilla text files, use Notepad
                  tgReadFile(cmd)
              ELSEIF cmdUC = "CLS" THEN
                 CLS ' clear console screen.. use Qn for graphic
              ELSEIF INSTR(cmdUC,"NOTEPAD") =1  THEN
                  pid=SHELL ("NOTEPAD.EXE",1)   'run asynchronously, same time as TGD
              ELSEIF INSTR(cmdUC,"PAINT") THEN
                  pid=SHELL ("MSPAINT.EXE",1)   'run asynchronously, same time as TGD
              ELSEIF INSTR(cmdUC,"PAGE") =1  THEN      'GOTO console page, row, column
                  DIM cm0 AS LONG, cm1 AS LONG, cmx AS LONG,cmY AS LONG
                  cmdUC +=SPACE$(2) 'pad it
                  cm0 = VAL(MID$(cmdUC,5))
                  IF cm0 > 0 AND cm0<9 THEN PAGE cm0,cm0     'switch console page
                  cm1 =TALLY (cmdUC,",")
                  IF cm1 = 0 THEN
                      cmY = 1: cmX =1
                  ELSE
                      IF cm1 > 0 THEN cmY = VAL(PARSE$(cmdUC,",",2))
                      IF cm1 > 1 THEN cmX = VAL(PARSE$(cmdUC,",",3))
                      IF cmX < 1 THEN cmX = CURSORX
                      IF cmY < 1 THEN cmy = CURSORY
                      IF cmX > MaxCol THEN cmX = MaxCol
                      IF cmY > MaxRow THEN cmy = MaxRow
                  END IF
                  LOCATE cmY, cmX
              ELSE
                 tgDraw(cmd)
              END IF
              tgUpdateScreen
              U.Done = 0
          END IF
      
          IF U.LB = 1 THEN
              'TGDRAW ON GRAPHICS SCREEN w/ mouse left button
              Dist = SQR((U.X - LastX)^2 +(U.Y - LastY)^2)
              IF Dist > 0 THEN
                  A$ = "M"+FORMAT$(U.X)+ "," + FORMAT$(U.Y)
                  IF Dist > turtle.DistGap THEN A$="B" + A$
                  '''stdout A$ + " ";    'record move
                  LastX=U.X
                  LastY=U.Y
                  tgDraw(A$)
                  tgUpdateScreen
              END IF
          ELSEIF U.RB = 1 THEN
              turtle.PX = U.X
              turtle.PY = U.Y
          END IF
      
      
          GOSUB ColorString:
          A$ = "TGD Graphics  Mouse " + FORMAT$(U.X,m1$) + "," + FORMAT$(U.Y,m1$)+_
               "  Turtle "+FORMAT$(INT(Turtle.PX),m2$) + "," + FORMAT$(INT(Turtle.PY),m2$)+_
               B$ + SPACE$(5)
      
          SetWindowText hGraphicWindow, (A$)    'win api  print on top line
          A$="TGD   Console      Page-Row-Col   "+FORMAT$(PAGEVISIBLE,m1$)+ ","+_
              FORMAT$(CURSORY,m1$) + "," + FORMAT$(CURSORX,m1$)
          CONSOLE NAME A$
          GRAPHIC GET DC TO hwin: IF hwin=0 THEN U.Finished = 1' Window was closed by [x] so Quit
          SLEEP 0
      
        WEND
      
        IF PAGEVISIBLE <> 1 THEN CLS: PAGE 1, 1
        GRAPHIC WINDOW END
        FUNCTION = 27   'ASC of Escape key
        EXIT FUNCTION
      
        '============ GOSUB =========================
        ColorString:
         'Petr's note re splitting color components
          '- there are various hacks, but one of the more elegant could be the following:
      
          ' -- Classic RGB color
          DIM rgbColor AS LONG
      
          #IF 0
      
          GetCursorPos Pt                           'win api mouse pos
          ScreenToClient hGraphicWindow, pt                   'win api mouse pos on graph per se
          IF U.X<>Pt.X OR U.Y<>Pt.Y THEN
              STDOUT "Mouse readings do not agree"+FORMAT$(Pt.X)+","+FORMAT$(Pt.Y)+"   "+FORMAT$(U.X)+","+FORMAT$(U.Y)
              WAITKEY$
          END IF
          #ENDIF
      
          GRAPHIC GET PIXEL (U.X, U.Y) TO rgbColor   'color at mouse's "hot spot"
          'rgbColor = RGB(255, 128, 64)
      
          ' -- We want to extract components - lets use memory overlays
          DIM MyColor(1 TO 3) AS BYTE AT VARPTR(rgbColor)
          ' -- Now MyColor(1) = R, MyColor(2) = G, MyColor(3) = B
      
          'Is this one of the 16 color values used by function tgColorVal?
          FOR I = 0 TO 15
              IF rgbColor = tgColorVal(I) THEN EXIT FOR
          NEXT
          IF I > 15 THEN B$="DOScolor ?? -" ELSE B$="DOScolor"+STR$(I)
          B$ += " RGB " + STR$(MyColor(1))+ "," + STR$(MyColor(2))+ "," + STR$(MyColor(3))
          RETURN
      END FUNCTION
      Last edited by Emil Menzel; 11 Aug 2009, 07:22 AM.

      Comment


      • #4
        You can download complete turtle package from this post.
        It contains:
        • New examples
        • Improved documentation
        • ... and of course the turtle include file


        It is recommended to use PB/WIN 9 and PB/CC 5 series of the compilers.
        Attached Files
        [email protected]

        Comment


        • #5
          I thought this might be a good demo. It was a homework for my computer science class.

          Code:
          #COMPILE EXE
          #DIM ALL
          
          #INCLUDE "tgDraw.inc"
          
          SUB resetTree()
            tgClearScreen()
            tgPenUp()
            tgRight(90)
            tgForward(250)
            tgRight(180)
            tgPenDown()
          END SUB
          
          SUB init()
            LOCAL hWnd AS DWORD, Xmax AS SINGLE, Ymax AS SINGLE
          
            Xmax=800: Ymax=600
            CONSOLE SET LOC 0, 0
            GRAPHIC WINDOW "Recur Tree", 700, 0, Xmax, Ymax TO hWnd
            tgAttachGraphic(hWnd, 0, %TG_DOUBLE_BUFFER)
            tgSetColor(%TG_WHITE, %TG_BLACK)
            resetTree
          END SUB
          
          SUB drawTree(se AS LONG, si AS LONG)
              IF se <> 0 THEN
                  tgForward(si)
                  tgLeft(45)
                  tgSetColor(RND(1,15), %TG_BLACK)
                  drawTree se - 1, si/1.5
                  tgRight(90)
                  drawTree se - 1, si/1.5
                  tgLeft(45)
                  tgForward(-si)
                  'tgUpdateScreen()
              END IF
          END SUB
          
          
          FUNCTION PBMAIN () AS LONG
              LOCAL treeSeg AS LONG
              LOCAL treeSize AS LONG
              LOCAL again AS STRING
          
              init
              again = "y"
              WHILE again = "y" OR again = "Y"
                  INPUT "Type the number of tree segments: ", treeSeg
                  INPUT "Type the length of each segment: ", treeSize
                  resetTree
                  drawTree treeSeg, treeSize
                  tgUpdateScreen()
                  PRINT "Try again(y/n)?"
                  again = WAITKEY$
              WEND
              PRINT "Any key to exit. . ."
              WAITKEY$
          END FUNCTION

          Comment


          • #6
            Such a nice example, can we add it to the Samples for tgDraw in next release?


            Petr
            [email protected]

            Comment


            • #7
              Sure. If I post it, then you can use it however you want. Anyway, I have one more coming out, but I'm having trouble with it.

              Comment


              • #8
                Here's the next one. This one draws flower like things.

                Code:
                #COMPILE EXE
                #DIM ALL
                
                #INCLUDE "tgDraw.inc"
                
                GLOBAL color1 AS LONG
                GLOBAL color2 AS LONG
                
                SUB init()
                  LOCAL hWnd AS DWORD
                
                  GRAPHIC WINDOW "Flowers", 700, 0, 800, 600 TO hWnd
                  tgAttachGraphic(hWnd, 0, %TG_DOUBLE_BUFFER)
                  tgSetColor(%TG_WHITE, %TG_BLACK)
                  tgClearScreen()
                END SUB
                
                SUB drawFlower(length AS INTEGER, BYVAL pedals AS INTEGER, angle AS INTEGER)
                    IF pedals <> 0 THEN
                        IF pedals MOD 2 THEN
                            tgSetColor(color1, %TG_BLACK)
                        ELSE
                            tgSetColor(color2, %TG_BLACK)
                        END IF
                        tgRight(angle)
                        drawBox 4, length
                        DECR pedals
                        drawFlower length, pedals, angle
                    ELSE
                        tgSetColor(%TG_LIGHTGREEN, %TG_BLACK)
                        tgSetWidth(3)
                        tgRight(90)
                        tgForward(length * 4)
                        tgSetWidth(1)
                    END IF
                END SUB
                
                SUB drawBox(sides AS INTEGER, length AS INTEGER)
                    IF sides <> 0 THEN
                        tgForward(length)
                        tgRight(90)
                        DECR sides
                        drawBox sides, length
                    END IF
                END SUB
                
                FUNCTION PBMAIN () AS LONG
                    LOCAL angle AS INTEGER
                    LOCAL length AS INTEGER
                    LOCAL pedals AS INTEGER
                    LOCAL amount AS INTEGER
                    LOCAL i AS INTEGER
                
                    CONSOLE SET LOC 0, 0
                    PRINT "Test Cases"
                    PRINT "=========="
                    PRINT "Dandelion = 20, 15, 40, 8, 15"
                    PRINT "Medium = 30, 30, 50, 14, 15"
                    PRINT "Large = 60, 100, 1, 5, 14"
                    PRINT ""
                    INPUT "Type the number of pedals: ", pedals
                    INPUT "Type the length of each pedal: ", length
                    INPUT "How many? ", amount
                    INPUT "Color #1: ", color1
                    INPUT "Color #2: ", color2
                    init
                    angle = 360/pedals
                    RANDOMIZE TIMER
                    FOR i = 1 TO amount
                        tgSetPos(RND(1,800), RND(1,600))
                        drawFlower length, pedals, angle
                        tgUpdateScreen()
                    NEXT i
                    CONSOLE SET FOCUS
                    PRINT "Any key. . ."
                    WAITKEY$
                END FUNCTION

                Comment

                Working...
                X