-- Jake Lever s0564148 -- To run my entry to the competition execute the command "display 0.1 (makelotsofstars 10)" -- It may take a few seconds to calculate all the commands import LSystem opt :: Command opt = Go 10 :# (Sit :# (Go 20 :# Turn 35)) :# Go 0 :# Turn 15 :# Turn (-50) -- 1. join :: [Command] -> Command join [] = Sit join (x:[]) = x join (x:rest) = x :# join rest -- 2. split :: Command -> [Command] split (first :# sec) = (split first) ++ (split sec) split x = [x] -- 3. copy :: Int -> Command -> Command copy n c = join (replicate n c) -- 4. hexagon :: Distance -> Command hexagon n = copy 6 (Go n :# Turn 60) -- 5. polygon :: Distance -> Int -> Command polygon n s = copy s (Go n :# Turn (fromIntegral (360 `div` s))) -- 6. spiral :: Distance -> Int -> Distance -> Angle -> Command spiral start 1 step ang = Go start :# Turn ang spiral start iter step ang = Go start :# Turn ang :# (spiral (start - step) (iter - 1) step ang) -- 7. optimise :: Command -> Command optimise c = join (optimise' (split c) False) optimise' :: [Command] -> Bool -> [Command] -- List of commands and whether it's been optimised optimise' [] _ = [] optimise' [Sit] _ = [] optimise' [Go 0] _ = [] optimise' [Turn 0] _ = [] optimise' (Sit : rest) _ = optimise' rest False optimise' (Go 0 : rest) _ = optimise' rest False optimise' (Turn 0 : rest) _ = optimise' rest False optimise' (Go x : Go y : rest) _ = optimise' (Go (x+y) : rest) False optimise' (Turn x : Turn y : rest) _ = optimise' (Turn (x+y) : rest) False optimise' (x:rest) op |op == True = x : optimise' rest False |op == False = optimise' (x : optimise' rest False) True -- 8. arrowhead :: Int -> Command arrowhead x = f x where f 0 = GrabPen red :# Go 10 f (x+1) = g x :# p :# f x :# p :# g x g 0 = GrabPen blue :# Go 10 g (x+1) = f x :# n :# g x :# n :# f x n = Turn 60 p = Turn (-60) -- 9. branch :: Int -> Command branch x = g x where f 0 = GrabPen red :# Go 10 f (x+1) = f x :# f x g 0 = GrabPen blue :# Go 10 g (x+1) = f x :# n :# Branch ( Branch ( g x) :# p :# g x) :# f x :# Branch (p :# f x :# g x) :# n :# p n = Turn 22.5 p = Turn (-22.5) -- 10. hilbert :: Int -> Command hilbert x = l x where l 0 = GrabPen red :# Go 10 l (x+1) = p :# r x :# f x :# n :# l x :# f x :# l x :# n :# f x :# r x :# p r 0 = GrabPen blue :# Go 10 r (x+1) = n :# l x :# f x :# p :# r x :# f x :# r x :# p :# f x :# l x :# n f x = GrabPen green :# Go 10 n = Turn 90 p = Turn (-90) -- My Contest Things darkblue = Colour 0.0 0.0 0.9 darkerblue = Colour 0.0 0.0 0.5 mine1 :: Int -> Command mine1 x = f x where f 0 = GrabPen darkblue :# Go 10 f (x+1) = f x :# Branch (g x :# n :# h x :# p :# p) g 0 = GrabPen blue :# Go 15 g (x+1) = g x :# Branch (f x :# p :# p :# g x :# n) :# Branch (h x :# n :# f x) h 0 = GrabPen darkerblue :# Go 10 h (x+1) = Branch (f x :# h x :# g x :# n) :# n :# f 0 n = Turn 10 p = Turn (-50) mine2 :: Int -> Command mine2 x = f x where f 0 = GrabPen darkerblue :# Go 10 f (x+1) = Branch (f x) :# n :# g x g 0 = GrabPen blue :# Go 10 g (x+1) = n :# Branch (g x :# p :# g x) :# Branch (n :# g x) :# f x :# p :# g x n = Turn 20 p = Turn (-20) mine3 :: Int -> Command mine3 1 = getcurve 1 50 mine3 x = getcurve x 50 :# mine3 (x-1) multiplier, increment, modulus :: Int multiplier = 25173 increment = 13849 modulus = 65536 getcurves :: Int -> Command getcurves n = join [GrabPen (randColour y) :# (getcurve x 100) | (x,y) <- (zip (randomSequence n 3213 100) (randomSequence n 7317 6))] getstar :: Int -> Command getstar n = join [GrabPen (randColour y) :# Branch (starcurve x) | (x,y) <- (zip (randomSequence n 122387 1000) (randomSequence n 7391 6))] starcurve :: Int -> Command starcurve x = stepcurve (fromIntegral x) 50 getcurve :: Int -> Int -> Command getcurve x rmax | x < (rmax `div` 4) = stepcurve (fromIntegral x) 50 | x < (rmax `div` 3) = Turn 90 :# stepcurve (fromIntegral x) 40 | x < (rmax `div` 2) = Turn 180 :# stepcurve (fromIntegral x) 30 | otherwise = Turn 270 :# stepcurve (fromIntegral x) 20 stepcurve :: Float -> Float -> Command stepcurve size angle | size < 10 || angle < 3 = Go size :# Turn angle | otherwise = Go size :# Turn angle :# stepcurve (0.9 * size) (0.9 * angle) nextRand :: Int -> Int nextRand n = (multiplier*n + increment) `mod` modulus randomSequence :: Int -> Int -> Int -> [Int] randomSequence 0 seed rmax = [] randomSequence len seed rmax = (nextRand seed) `div` (modulus `div` rmax) : randomSequence (len-1) (nextRand seed) rmax randColour :: Int -> Pen randColour x | x == 0 = black -- Black | x == 1 = red -- Red | x == 2 = green -- Green | x == 3 = blue -- Blue | x == 4 = mix red green -- Yellow | x == 5 = mix red blue -- Purple | x == 6 = mix green blue -- Cyan randColour2 :: Int -> Pen randColour2 x = head [Colour ((fromIntegral x)/1000) ((fromIntegral y)/1000) ((fromIntegral z)/1000) | (x,y,z) <- (zip3 (randomSequence 1 (x `mod` 12397) 1000) (randomSequence 1 (x `mod` 23411) 1000) (randomSequence 1 (x `mod` 65536) 1000))] makestar :: Int -> Int -> Command makestar x col = GrabPen (randColour2 col) :# join [Turn 5 :# Branch (Go (fromIntegral y)) | y <- randomSequence x 434341 100] makestars :: Int -> Command makestars x = join [Branch((makestar y z)) :# Turn 10 :# GrabPen white :# Go 200| (y,z) <- (zip (randomSequence x 12913 1000) (randomSequence x 98397 65000))] makelotsofstars :: Int -> Command makelotsofstars x = GrabPen white :# Turn 270 :# Go 2500 :# Turn 90 :# Go 100 :# join [makestars 30 :# Turn 90 :# Go 50 :# Turn (-60) | y <- [0..x]]