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 @@
+
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 states = new Stack();
+ 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;
}
}
}