From 8fcadb007ff9004e6e54f96b3a6c6345b2dc5168 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Sun, 4 Nov 2018 13:55:27 +0000
Subject: [PATCH] Try to imlement [ and ], but it's not quite right yet?

---
 SimpleTurtle/Area.cs             |  19 +++++
 SimpleTurtle/Help.txt            |   2 +
 SimpleTurtle/SimpleTurtle.csproj |   1 +
 SimpleTurtle/Turtle.cs           | 121 +++++++++++++++++--------------
 4 files changed, 90 insertions(+), 53 deletions(-)
 create mode 100644 SimpleTurtle/Area.cs

diff --git a/SimpleTurtle/Area.cs b/SimpleTurtle/Area.cs
new file mode 100644
index 0000000..8d8c94b
--- /dev/null
+++ b/SimpleTurtle/Area.cs
@@ -0,0 +1,19 @@
+﻿using System;
+namespace SBRL.SimpleTurtle
+{
+	public class Area
+	{
+		public double X;
+		public double Y;
+		public double Width;
+		public double Height;
+
+		public Area(double inX, double inY, double inWidth, double inHeight)
+		{
+			X = inX;
+			Y = inY;
+			Width = inWidth;
+			Height = inHeight;
+		}
+	}
+}
diff --git a/SimpleTurtle/Help.txt b/SimpleTurtle/Help.txt
index 95b55e7..efb93c8 100644
--- a/SimpleTurtle/Help.txt
+++ b/SimpleTurtle/Help.txt
@@ -23,6 +23,8 @@ Input File Format:
         h   Also move forwards
         +   Turn clockwise
         -   Turn anti-clockwise
+        [   Save position & heading to stack
+        ]   Restore position & heading from stack
 
     Turtle Directives:
         angle    Sets the angle by which the turtle should turn. Note that this is specified in radians.
diff --git a/SimpleTurtle/SimpleTurtle.csproj b/SimpleTurtle/SimpleTurtle.csproj
index 26215a9..379c242 100644
--- a/SimpleTurtle/SimpleTurtle.csproj
+++ b/SimpleTurtle/SimpleTurtle.csproj
@@ -42,6 +42,7 @@
     <Compile Include="LSystemEngine.cs" />
     <Compile Include="Utilities\EmbeddedFiles.cs" />
     <Compile Include="Utilities\Timer.cs" />
+    <Compile Include="Area.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Help.txt">
diff --git a/SimpleTurtle/Turtle.cs b/SimpleTurtle/Turtle.cs
index 76d426b..db346ce 100755
--- a/SimpleTurtle/Turtle.cs
+++ b/SimpleTurtle/Turtle.cs
@@ -6,44 +6,40 @@ using System.Collections.Generic;
 
 namespace SBRL.SimpleTurtle
 {
-	public class Area
-	{
-		public double X;
-		public double Y;
-		public double Width;
-		public double Height;
+	public class TurtleState : ICloneable {
+		public PointD Position;
+		public double Heading;
 
-		public Area(double inX, double inY, double inWidth, double inHeight)
-		{
-			X = inX;
-			Y = inY;
-			Width = inWidth;
-			Height = inHeight;
+		public TurtleState(PointD inPosition, double inHeading) {
+			Position = inPosition;
+			Heading = inHeading;
+		}
+
+		public object Clone() {
+			return new TurtleState(Position, Heading);
 		}
 	}
+
 	public class Turtle
 	{
-		private bool strictMode = false;
+		public bool StrictMode = false;
 		private string commandQueue;
 
-		private PointD position;
+		private readonly Stack<TurtleState> states = new Stack<TurtleState>();
+		public PointD Position {
+			get => states.Peek().Position;
+			protected set => states.Peek().Position = value;
+		}
+		public double Heading {
+			get => states.Peek().Heading;
+			protected set => states.Peek().Heading = value;
+		}
 		private Area bounds;
-		private double heading;
-		private double headingStep;
-		public double HeadingStep
-		{
-			get { return headingStep; }
-			set { headingStep = value; }
-		}
-		private double movementStep ;
-		public double MovementStep
-		{
-			get { return movementStep; }
-			set { movementStep = value; }
-		}
 
-		public Turtle ()
-		{
+		public double HeadingStep { get; set; }
+		public double MovementStep { get; set; }
+
+		public Turtle () {
 			Reset();
 		}
 
@@ -83,15 +79,21 @@ namespace SBRL.SimpleTurtle
 						case '-':
 							Turn(true);
 							break;
+						case '[':
+							Save();
+							break;
+						case ']':
+							Restore();
+							break;
 						default:
-							if (strictMode) {
+							if (StrictMode) {
 								Console.WriteLine("The unexpected character '{0}' slipped through the net!", ch);
 								return false;
 							}
 							break;
 					}
 				}
-				else if(strictMode)
+				else if(StrictMode)
 				{
 					Console.Error.WriteLine("Error: unexpected character '{0}'", ch);
 					return false;
@@ -105,28 +107,28 @@ namespace SBRL.SimpleTurtle
 		{
 			ImageSurface canvas = new ImageSurface(Format.ARGB32, (int)Math.Ceiling(bounds.Width + 10), (int)Math.Ceiling(bounds.Height + 10));
 			Context context = new Context(canvas);
-			position = new PointD(-bounds.X + 5, -bounds.Y + 5);
-			heading = 0;
+			Position = new PointD(-bounds.X + 5, -bounds.Y + 5);
+			Heading = 0;
 
 			context.LineWidth = 3;
-			context.MoveTo(position);
+			context.MoveTo(Position);
 			foreach(char ch in commandQueue)
 			{
 				switch(ch)
 				{
 					case 'f':
 						PointD newPosition = new PointD(
-							position.X + movementStep * Math.Sin(heading),
-							position.Y + movementStep * Math.Cos(heading)
+							Position.X + MovementStep * Math.Sin(Heading),
+							Position.Y + MovementStep * Math.Cos(Heading)
 						);
 						context.LineTo(newPosition);
-						position = newPosition;
+						Position = newPosition;
 						break;
 					case '+':
-						heading += headingStep;
+						Heading += HeadingStep;
 						break;
 					case '-':
-						heading -= headingStep;
+						Heading -= HeadingStep;
 						break;
 				}
 			}
@@ -142,44 +144,57 @@ namespace SBRL.SimpleTurtle
 		public void Forwards()
 		{
 			PointD newPosition = new PointD(
-				position.X + MovementStep * Math.Sin(heading),
-				position.Y + MovementStep * Math.Cos(heading)
+				Position.X + MovementStep * Math.Sin(Heading),
+				Position.Y + MovementStep * Math.Cos(Heading)
 			);
 
 			if (newPosition.X > bounds.X + bounds.Width)
-				bounds.Width += newPosition.X - position.X;
+				bounds.Width += newPosition.X - Position.X;
 			if (newPosition.Y > bounds.Y + bounds.Height)
-				bounds.Height += newPosition.Y - position.Y;
+				bounds.Height += newPosition.Y - Position.Y;
 			if (newPosition.X < bounds.X)
 			{
 				bounds.X = newPosition.X;
-				bounds.Width += position.X - newPosition.X;
+				bounds.Width += Position.X - newPosition.X;
 			}
 			if (newPosition.Y < bounds.Y)
 			{
 				bounds.Y = newPosition.Y;
-				bounds.Height += position.Y - newPosition.Y;
+				bounds.Height += Position.Y - newPosition.Y;
 			}
 
-			position = newPosition;
+			Position = newPosition;
 		}
 
 		public void Turn(bool anticlockwise = false)
 		{
 			if (!anticlockwise)
-				heading += HeadingStep;
+				Heading += HeadingStep;
 			else
-				heading -= HeadingStep;
+				Heading -= HeadingStep;
+		}
+
+		public void Save()
+		{
+			states.Push(states.Peek().Clone() as TurtleState);
+		}
+		public bool Restore() {
+			if (states.Count <= 1)
+				return false;
+
+			states.Pop();
+			return true;
 		}
 
 		public void Reset()
 		{
+			states.Clear();
+			states.Push(new TurtleState(new PointD(0, 0), 0));
+
 			commandQueue = string.Empty;
-			position = new PointD(0, 0);
-			bounds = new Area(position.X, position.Y, 1, 1);
-			heading = 0;
-			headingStep = Math.PI / 2;
-			movementStep = 25;
+			bounds = new Area(Position.X, Position.Y, 1, 1);
+			HeadingStep = Math.PI / 2;
+			MovementStep = 25;
 		}
 	}
 }
