############################################################################
#
#       File:     lsys.icn
#
#	Subject:  Program to experiment with Lindenmayer systems
#
#	Author:   Stephen B. Wampler
#
#	Date:     June 17, 1994
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#	Version:  1.0
#
############################################################################
#
#
#   Comments: This program display Lindenmayer systems using
#	turtle graphics.  There are some built-in L-systems,
#       but users can easily modify these and construct new
#	systems.
#
#	See the procedure 'helpmsg' for command line options
#	(or run as 'lsys -help')
#
#	Waits for a window event before closing window
#
############################################################################
#
#	Requires:  Version 9 graphics and co-expressions (for glib.icn)
#
############################################################################
#
#	Links: glib, lsystem, wopen
#
############################################################################


link glib		# need the turtle graphics stuff
link lsystem		# ...and the L-System stuff
link wopen

global win, mono, h, w
global Window, XMAX, YMAX

global pre_defs

procedure main (args)
    local ls, arg, t

    XMAX := YMAX := 700                 # physical screen size
    w := h := 700.0
   

    init_pre_defs()			# table of predefined L-systems

    ls := pre_defs["koch_island"]

    while arg := get(args) do {
       case arg of {
          "-help"|"-h" : helpmsg()
          "-order"|"-o": ls.order := integer(get(args))
          "-dist" |"-d": ls.dist  := numeric(get(args))
          "-delta"     : ls.delta := numeric(get(args))
          "-axiom"|"-a": ls.axiom := get(args)
          "-map"       : ls.rewrite[get(args)] := get(args)
          "-file"|"-f" : ls := read_Lsystem(open(get(args)))
          "-name"|"-n" : ls := \pre_defs[get(args)]
          "-describe"  : {
                         write_Lsystem(ls := \(pre_defs[write(get(args))]))
                         write()
                         }
          }
       if arg == ("-help"|"-h") then stop(helpmsg())
       }

    win := WOpen("label=L-System", "width="||XMAX, "height="||YMAX)
    mono := WAttrib (win, "depth") == "1"
    Window := set_window(win, point(0,0), point(w,h),
                  viewport(point(0,0), point(XMAX, YMAX), win))

    EraseArea(win)

    t := turtle(Window, point(w/2, h/2), 0, create |"red")

    eval_lsys(t,ls)
# These two commands are behaviorally equivalent to the above line,
#   but trade numerous recursive calls (above) for a *long* command
#   string...
#    s := build_cmd(ls)
#    eval_cmd(t, s, ls.dist, ls.delta)

    # sit and wait for an event on the window.
    Event(win)
    close(win)
end

procedure helpmsg()
   write("Usage: Lsys [[-o n] [-d r] [-delta r] [-axiom s] [-map c s]... ]")
   write("        [-f file] [-n name] [-describe name]")
   write("   where")
   write("     -o n		-- order of system")
   write("     -d r		-- line length")
   write("     -delta r		-- angle for turns")
   write("     -axiom s		-- initial axiom")
   write("     -map c S		-- rewrite rule mapping c into s")
   write("     -f file		-- read Lsystem from file")
   write("     -n name		-- use predefined Lsystem 'name'")
   write("     -describe name	-- describe (and use) predefined Lsystem 'name'")
   write(" ")
   write("   Options are processed in order from left to right, e.g.")
   write(" ")
   write("     Lsys -n koch_island -o 3")
   write(" ")
   write("   displays an order 3 koch_island.")
   write(" ")
   write("   Available predefined Lsystems are:\n")
   every write("     ",key(pre_defs))
   stop()
end

procedure init_pre_defs()

   pre_defs := table()

   pre_defs["koch_island"] := Lsys(1,10,90,"F-F-F-F",
                                   mk_map([["F","F-F+F+FF-F-F+F"]]))
   pre_defs["box_swirls"] := Lsys(1,10,90,"F-F-F-F",
                                   mk_map([["F","FF-F-F-F-F-F+F"]]))
   pre_defs["squares"] := Lsys(1,10,90,"F-F-F-F",
                                   mk_map([["F","FF-F-F-F-FF"]]))
   pre_defs["soot"] := Lsys(1,10,90,"F-F-F-F",
                                   mk_map([["F","FF-F--F-F"]]))
   pre_defs["box_flake"] := Lsys(1,10,90,"F-F-F-F",
                                   mk_map([["F","F-FF--F-F"]]))
   pre_defs["dragon"] := Lsys(1,10,90,"L",
                                   mk_map([["L","L+R+"],["R","-L-R"]]))
   pre_defs["triangle"] := Lsys(1,10,60,"R",
                                   mk_map([["L","R+L+R"],["R","L-R-L"]]))
   pre_defs["flake"] := Lsys(1,10,60,"L",
                                   mk_map([["L","L+R++R-L--LL-R+"],
                                           ["R","-L+RR++R+L--L-R"]]))
   pre_defs["near_hilbert"] := Lsys(1,10,90,"-R",
        mk_map([["L","LL-R-R+L+L-R-RL+R+LLR-L+R+LL+R-LR-R-L+L+RR-"],
               ["R","+LL-R-R+L+LR+L-RR-L-R+LRR-L-RL+L+R-R-L+L+RR"]]))

end
