Wrapping up ActorImage and started adding ActorIKTarget.
diff --git a/Source/Actor.cpp b/Source/Actor.cpp
index cb3aa42..d3baae5 100644
--- a/Source/Actor.cpp
+++ b/Source/Actor.cpp
@@ -1,4 +1,6 @@
 #include "Actor.hpp"
+#include "ActorBone.hpp"
+#include "ActorRootBone.hpp"
 #include "BinaryReader.hpp"
 #include "BlockReader.hpp"
 #include "Exceptions/OverflowException.hpp"
@@ -6,7 +8,15 @@
 
 using namespace nima;
 
-Actor::Actor() : m_NodeCount(0), m_Nodes(NULL), m_Root(new ActorNode())
+Actor::Actor() : 
+			m_NodeCount(0), 
+			m_Nodes(NULL), 
+			m_Root(new ActorNode()),
+			m_MaxTextureIndex(0),
+			m_ImageNodeCount(0),
+			m_SolverNodeCount(0),
+			m_ImageNodes(NULL),
+			m_Solvers(NULL)
 {
 
 }
@@ -19,6 +29,8 @@
 		delete m_Nodes[i];	
 	}
 	delete [] m_Nodes;
+	delete [] m_ImageNodes;
+	delete [] m_Solvers;
 }
 
 Actor* Actor::fromBytes(unsigned char* bytes, unsigned int length)
@@ -103,6 +115,27 @@
 			case BlockReader::ActorNode:
 				node = ActorNode::read(this, nodeBlock);
 				break;
+			case BlockReader::ActorBone:
+				node = ActorBone::read(this, nodeBlock);
+				break;
+			case BlockReader::ActorRootBone:
+				node = ActorRootBone::read(this, nodeBlock);
+				break;
+			case BlockReader::ActorImage:
+			{
+				m_ImageNodeCount++;
+				node = ActorImage::read(this, nodeBlock);
+				ActorImage* imageNode = reinterpret_cast<ActorImage*>(node);
+				if(imageNode->textureIndex() > m_MaxTextureIndex)
+				{
+					m_MaxTextureIndex = imageNode->textureIndex();
+				}
+				break;
+			}
+			case BlockReader::ActorIKTarget:
+				m_SolverNodeCount++;
+				break;
+
 			default:
 				// Name is first thing in each block.
 				{
@@ -114,4 +147,31 @@
 		m_Nodes[nodeIndex] = node;
 		nodeIndex++;
 	}
+
+	m_ImageNodes = new ActorImage*[m_ImageNodeCount];
+	m_Solvers = new Solver*[m_SolverNodeCount];
+
+	// Resolve nodes.
+	int imdIdx = 0;
+	int slvIdx = 0;
+	for(int i = 1; i < m_NodeCount; i++)
+	{
+		ActorNode* n = m_Nodes[i];
+		if(n != NULL)
+		{
+			n->resolveNodeIndices(m_Nodes);
+
+			switch(n->type())
+			{
+				case Node::Type::ActorImage:
+					m_ImageNodes[imdIdx++] = reinterpret_cast<ActorImage*>(n);
+					break;
+				case Node::Type::ActorIKTarget:
+					m_Solvers[slvIdx++] = reinterpret_cast<Solver*>(n);
+					break;
+				default:
+					break;
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/Source/Actor.hpp b/Source/Actor.hpp
index 839634f..8ec0392 100644
--- a/Source/Actor.hpp
+++ b/Source/Actor.hpp
@@ -2,7 +2,9 @@
 #define _NIMA_ACTOR_HPP_
 
 #include "ActorNode.hpp"
+#include "ActorImage.hpp"
 #include "BlockReader.hpp"
+#include "Solver.hpp"
 
 namespace nima
 {
@@ -17,6 +19,14 @@
 			ActorNode** m_Nodes;
 			ActorNode* m_Root;
 			void readNodesBlock(BlockReader* block);
+		
+		protected:
+			int m_MaxTextureIndex;
+			int m_ImageNodeCount;
+			int m_SolverNodeCount;
+
+			ActorImage** m_ImageNodes;
+			Solver** m_Solvers;
 
 		public:
 			static Actor* fromBytes(unsigned char* bytes, unsigned int length);
diff --git a/Source/ActorIKTarget.cpp b/Source/ActorIKTarget.cpp
new file mode 100644
index 0000000..fe55111
--- /dev/null
+++ b/Source/ActorIKTarget.cpp
@@ -0,0 +1,211 @@
+#include "ActorIKTarget.hpp"
+#include "BlockReader.hpp"
+
+using namespace nima;
+
+ActorIKTarget::InfluencedBone::InfluencedBone() : boneIndex(0), bone(NULL)
+{
+
+}
+
+ActorIKTarget::ActorIKTarget() :
+		ActorNode(Node::Type::ActorIKTarget),
+
+		m_NumInfluencedBones(0),
+		m_InfluencedBones(NULL),
+		m_InvertDirection(false),
+		m_Strength(0.0f),
+		m_Order(0),
+		m_Bone1(NULL),
+		m_Bone1Child(NULL),
+		m_Bone2(NULL),
+		m_Chain(NULL)
+{
+
+}
+
+ActorIKTarget::~ActorIKTarget()
+{
+	delete m_InfluencedBones;
+	delete m_Chain;
+}
+
+ActorNode* ActorIKTarget::makeInstance(Actor* resetActor)
+{
+	ActorIKTarget* instanceNode = new ActorIKTarget();
+	instanceNode->copy(this, resetActor);
+	return instanceNode;
+}
+
+void ActorIKTarget::copy(ActorIKTarget* node, Actor* resetActor)
+{
+	Base::copy(node, resetActor);
+
+	m_Order = node->m_Order;
+	m_InvertDirection = node->m_InvertDirection;
+	m_Strength = node->m_Strength;
+	m_NumInfluencedBones = node->m_NumInfluencedBones;
+	m_InfluencedBones = new InfluencedBone[m_NumInfluencedBones];
+	for(int i = 0; i < m_NumInfluencedBones; i++)
+	{
+		InfluencedBone& ib = m_InfluencedBones[i];
+		ib.boneIndex = node->m_InfluencedBones[i].boneIndex;
+	}
+}
+
+ActorIKTarget* ActorIKTarget::read(Actor* actor, BlockReader* reader, ActorIKTarget* node)
+{
+	if(node == NULL)
+	{
+		node = new ActorIKTarget();
+	}
+
+	Base::read(actor, reader, node);
+
+	node->m_Order = reader->readUnsignedShort();
+	node->m_Strength = reader->readFloat();
+	node->m_InvertDirection = reader->readByte() == 1;	
+
+	node->m_NumInfluencedBones = (int)reader->readByte();
+	if(node->m_NumInfluencedBones > 0)
+	{
+		node->m_InfluencedBones = new InfluencedBone[node->m_NumInfluencedBones];
+		for(int i = 0; i < node->m_NumInfluencedBones; i++)
+		{
+			InfluencedBone& ib = node->m_InfluencedBones[i];
+			ib.boneIndex = reader->readUnsignedShort();
+		}
+	}
+
+	return node;
+}
+
+void ActorIKTarget::resolveNodeIndices(ActorNode** nodes)
+{
+	Base::resolveNodeIndices(nodes);
+	if(m_InfluencedBones != NULL)
+	{
+		for(int i = 0; i < m_NumInfluencedBones; i++)
+		{
+			InfluencedBone& ib = m_InfluencedBones[i];
+			ib.bone = reinterpret_cast<ActorBone*>(nodes[ib.boneIndex]);
+			ib.bone->addDependent(this);
+		}
+
+		m_Bone1 = m_InfluencedBones[0].bone;
+		m_Bone2 = m_InfluencedBones[m_NumInfluencedBones-1].bone;
+		ActorBone* b1c = m_Bone2;
+		ActorBone* b1 = m_Bone1;
+		while(b1c != NULL && b1c->parent() != b1)
+		{
+			ActorNode* n = b1c->parent();
+			if(n != NULL && n->type() == Node::Type::ActorBone)
+			{
+				b1c = reinterpret_cast<ActorBone*>(n);
+			}
+			else
+			{
+				b1c = NULL;
+			}
+		}
+		m_Bone1Child = b1c;
+
+		int chainCount = 0;
+		ActorNode* end = m_Bone2;
+		while(end != NULL && end != b1->parent())
+		{
+			chainCount++;
+
+			ActorNode* n = end->parent();
+			if(n != NULL && n->type() == Node::Type::ActorBone)
+			{
+				end = n;
+			}
+			else
+			{
+				end = NULL;
+			}
+		}
+
+		m_Chain = new BoneChain[chainCount];
+		end = m_Bone2;
+		int chainIndex = 0;
+		while(end != NULL && end != b1->parent())
+		{
+			BoneChain& bc = m_Chain[chainIndex];
+			bc.bone = reinterpret_cast<ActorBone*>(end);
+			ActorNode* n = end->parent();
+			if(n != NULL && n->type() == Node::Type::ActorBone)
+			{
+				end = n;
+			}
+			else
+			{
+				end = NULL;
+			}
+
+			bc.included = doesInfluence(bc.bone) || doesInfluence(reinterpret_cast<ActorBone*>(end)); // end is either null or an actorbone (for sure) here.
+			bc.angle = 0.0f;
+		}
+	}
+}
+
+bool ActorIKTarget::doesInfluence(ActorBone* bone)
+{
+	if(bone == NULL)
+	{
+		return false;
+	}
+	for(int i = 0; i < m_NumInfluencedBones; i++)
+	{
+		if(m_InfluencedBones[i].bone == bone)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+int ActorIKTarget::order()
+{
+	return m_Order;
+}
+
+bool ActorIKTarget::needsSolve()
+{
+	return isWorldDirty() || isDirty();
+}
+
+float ActorIKTarget::strength()
+{
+	return m_Strength;
+}
+
+void ActorIKTarget::strength(float s)
+{
+	if(m_Strength != s)
+	{
+		m_Strength = s;
+		markDirty();
+	}
+}
+
+bool ActorIKTarget::suppressMarkDirty()
+{
+	return Base::suppressMarkDirty();
+}
+
+void ActorIKTarget::suppressMarkDirty(bool suppressIt)
+{
+	Base::suppressMarkDirty(suppressIt);
+}
+
+void ActorIKTarget::solveStart()
+{
+
+}
+
+void ActorIKTarget::solve()
+{
+
+}
\ No newline at end of file
diff --git a/Source/ActorIKTarget.hpp b/Source/ActorIKTarget.hpp
new file mode 100644
index 0000000..ebcdb58
--- /dev/null
+++ b/Source/ActorIKTarget.hpp
@@ -0,0 +1,65 @@
+#ifndef _NIMA_ACTORIKTARGET_HPP_
+#define _NIMA_ACTORIKTARGET_HPP_
+
+#include "ActorNode.hpp"
+#include "ActorBone.hpp"
+#include "Solver.hpp"
+
+namespace nima
+{
+	class Actor;
+	class BlockReader;
+	class ActorNode;
+
+	class ActorIKTarget : public ActorNode, public Solver
+	{
+		typedef ActorNode Base;
+		public:
+			struct InfluencedBone
+			{
+				unsigned short boneIndex;
+				ActorBone* bone;
+
+				InfluencedBone();
+			};
+		private:
+			int m_NumInfluencedBones;
+			InfluencedBone* m_InfluencedBones;
+			bool m_InvertDirection;
+			float m_Strength;
+			int m_Order;
+
+			ActorBone* m_Bone1;
+			ActorBone* m_Bone1Child;
+			ActorBone* m_Bone2;
+
+			struct BoneChain
+			{
+				ActorBone* bone;
+				float angle;
+				bool included;
+			};
+
+			BoneChain* m_Chain;
+			bool doesInfluence(ActorBone* bone);
+
+		public:
+			ActorIKTarget();
+			~ActorIKTarget();
+			ActorNode* makeInstance(Actor* resetActor);
+			void copy(ActorIKTarget* node, Actor* resetActor);
+
+			int order();
+			bool needsSolve();
+			bool suppressMarkDirty();
+			void suppressMarkDirty(bool suppressIt);
+			void solveStart();
+			void solve();
+			float strength();
+			void strength(float s);
+			void resolveNodeIndices(ActorNode** nodes);
+
+			static ActorIKTarget* read(Actor* actor, BlockReader* reader, ActorIKTarget* node = NULL);
+	};
+}
+#endif
\ No newline at end of file
diff --git a/Source/ActorImage.cpp b/Source/ActorImage.cpp
index 5181325..3349236 100644
--- a/Source/ActorImage.cpp
+++ b/Source/ActorImage.cpp
@@ -1,12 +1,42 @@
 #include "ActorImage.hpp"
+#include "ActorBone.hpp"
 #include "BlockReader.hpp"
+#include <cstring>
 
 using namespace nima;
 
-ActorImage::ActorImage() : ActorNode(Node::Type::ActorImage)
+ActorImage::ActorImage() : 
+		ActorNode(Node::Type::ActorImage),
+
+		m_DrawOrder(0),
+		m_BlendMode(BlendModes::Normal),
+		m_TextureIndex(-1),
+		m_Vertices(NULL),
+		m_Triangles(NULL),
+		m_VertexCount(0),
+		m_TriangleCount(0),
+		m_AnimationDeformedVertices(NULL),
+		m_IsVertexDeformDirty(false),
+		m_BoneMatrices(NULL),
+		m_NumConnectedBones(0),
+		m_BoneConnections(NULL)
 {
 
 }
+
+ActorImage::BoneConnection::BoneConnection() : boneIndex(0), node(NULL)
+{
+
+}
+
+ActorImage::~ActorImage()
+{
+	delete [] m_Vertices;
+	delete [] m_Triangles;
+	delete [] m_AnimationDeformedVertices;
+	delete [] m_BoneMatrices;
+}
+
 ActorNode* ActorImage::makeInstance(Actor* resetActor)
 {
 	ActorImage* instanceNode = new ActorImage();
@@ -14,9 +44,119 @@
 	return instanceNode;
 }
 
+bool ActorImage::doesAnimationVertexDeform()
+{
+	return m_AnimationDeformedVertices != NULL;
+}
+
+void ActorImage::doesAnimationVertexDeform(bool doesIt)
+{
+	if(doesIt)
+	{
+		m_AnimationDeformedVertices = new float [m_VertexCount * 2];
+	}
+	else
+	{
+		delete [] m_AnimationDeformedVertices;
+		m_AnimationDeformedVertices = NULL;
+	}
+}
+
+float* ActorImage::animationDeformedVertices()
+{
+	return m_AnimationDeformedVertices;	
+}
+
+bool ActorImage::isVertexDeformDirty()
+{
+	return m_IsVertexDeformDirty;
+}
+
+void ActorImage::isVertexDeformDirty(bool isIt)
+{
+	m_IsVertexDeformDirty = isIt;
+}
+
+void ActorImage::disposeGeometry()
+{
+	// Delete vertices only if we do not vertex deform at runtime.
+	if(m_AnimationDeformedVertices == NULL)
+	{
+		delete [] m_Vertices;
+		m_Vertices = NULL;
+	}
+	delete [] m_Triangles;
+	m_Triangles = NULL;
+}
+
+int ActorImage::boneInfluenceMatricesLength()
+{
+	return m_NumConnectedBones == 0 ? 0 : (m_NumConnectedBones + 1) * 6;
+}
+float* ActorImage::boneInfluenceMatrices()
+{
+	if(m_BoneMatrices == NULL)
+	{
+		m_BoneMatrices = new float[boneInfluenceMatricesLength()];
+		// First bone transform is always identity.
+		m_BoneMatrices[0] = 1.0f;
+		m_BoneMatrices[1] = 0.0f;
+		m_BoneMatrices[2] = 0.0f;
+		m_BoneMatrices[3] = 1.0f;
+		m_BoneMatrices[4] = 0.0f;
+		m_BoneMatrices[5] = 0.0f;
+	}
+
+	Mat2D mat;
+	int bidx = 6;
+	for(int i = 0; i < m_NumConnectedBones; i++)
+	{
+		BoneConnection& bc = m_BoneConnections[i];
+		bc.node->updateTransforms();
+		Mat2D::multiply(mat, bc.node->worldTransform(), bc.ibind);
+		m_BoneMatrices[bidx++] = mat[0];
+		m_BoneMatrices[bidx++] = mat[1];
+		m_BoneMatrices[bidx++] = mat[2];
+		m_BoneMatrices[bidx++] = mat[3];
+		m_BoneMatrices[bidx++] = mat[4];
+		m_BoneMatrices[bidx++] = mat[5];
+	}
+
+	return m_BoneMatrices;
+}
+
 void ActorImage::copy(ActorImage* node, Actor* resetActor)
 {
+	Base::copy(node, resetActor);
 
+	m_DrawOrder = node->m_DrawOrder;
+	m_BlendMode = node->m_BlendMode;
+	m_TextureIndex = node->m_TextureIndex;
+	m_VertexCount = node->m_VertexCount;
+	m_TriangleCount = node->m_TriangleCount;
+	m_Vertices = node->m_Vertices;
+	m_Triangles = node->m_Triangles;
+	if(node->m_AnimationDeformedVertices != NULL)
+	{
+		int deformedVertexLength = m_VertexCount * 2;
+		m_AnimationDeformedVertices = new float[deformedVertexLength];
+		std::memmove(m_AnimationDeformedVertices, node->m_AnimationDeformedVertices, deformedVertexLength * sizeof(float));
+	}
+
+	if(node->m_BoneConnections != NULL)
+	{
+		m_NumConnectedBones = node->m_NumConnectedBones;
+		m_BoneConnections = new BoneConnection[node->m_NumConnectedBones];
+		for(int i = 0; i < m_NumConnectedBones; i++)
+		{
+			BoneConnection& bcT = m_BoneConnections[i];
+			BoneConnection& bcF = node->m_BoneConnections[i];
+
+			bcT.boneIndex = bcF.boneIndex;
+			Mat2D::copy(bcT.bind, bcF.bind);
+			Mat2D::copy(bcT.ibind, bcF.ibind);
+		} 
+	}
 }
 
 ActorImage* ActorImage::read(Actor* actor, BlockReader* reader, ActorImage* node)
@@ -26,7 +166,7 @@
 		node = new ActorImage();
 	}
 
-	ActorNode::read(actor, reader, node);
+	Base::read(actor, reader, node);
 
 	bool isVisible = reader->readByte() != 0;
 	if(isVisible)
@@ -35,22 +175,57 @@
 		node->m_DrawOrder = (int)reader->readUnsignedShort();
 		node->m_TextureIndex = (int)reader->readByte();
 
-		int numConnectedBones = (int)reader->readByte();
-		if(numConnectedBones != 0)
+		node->m_NumConnectedBones = (int)reader->readByte();
+		if(node->m_NumConnectedBones != 0)
 		{
-			node->m_BoneConnections = new BoneConnection[numConnectedBones];
-			for(int i = 0; i < numConnectedBones; i++)
+			node->m_BoneConnections = new BoneConnection[node->m_NumConnectedBones];
+			for(int i = 0; i < node->m_NumConnectedBones; i++)
 			{
 				BoneConnection& bc = node->m_BoneConnections[i];
-				bc->boneIndex = reader->readUnsignedShort();
-				reader->read(bc->bind);
-				Mat2D::invert(bc->ibind, bc->bind);
+				bc.boneIndex = reader->readUnsignedShort();
+				reader->read(bc.bind);
+				Mat2D::invert(bc.ibind, bc.bind);
 			}
 
 			Mat2D worldOverride;
 			reader->read(worldOverride);
 			node->overrideWorldTransform(worldOverride);
 		}
+
+		unsigned int numVertices = reader->readUnsignedInt();
+		int vertexStride = node->m_NumConnectedBones > 0 ? 12 : 4;
+		node->m_VertexCount = (int)numVertices;
+
+		unsigned int vertexLength = numVertices * vertexStride;
+		node->m_Vertices = new float[vertexLength];
+		reader->readFloatArray(node->m_Vertices, vertexLength);
+
+		unsigned int numTris = reader->readUnsignedInt();
+		node->m_TriangleCount = (int)numTris;
+
+		unsigned int triLength = numTris * 3;
+		node->m_Triangles = new unsigned short[triLength];
+		reader->readUnsignedShortArray(node->m_Triangles, triLength);
 	}
 	return node;
+}
+
+void ActorImage::resolveNodeIndices(ActorNode** nodes)
+{
+	Base::resolveNodeIndices(nodes);
+	if(m_BoneConnections != NULL)
+	{
+		for(int i = 0; i < m_NumConnectedBones; i++)
+		{
+			BoneConnection& bc = m_BoneConnections[i];
+			bc.node = nodes[bc.boneIndex];
+			ActorBone* bone = reinterpret_cast<ActorBone*>(bc.node);
+			bone->isConnectedToImage(true);
+		}
+	}
+}
+
+int ActorImage::textureIndex()
+{
+	return m_TextureIndex;
 }
\ No newline at end of file
diff --git a/Source/ActorImage.hpp b/Source/ActorImage.hpp
index 48363a9..dd6f845 100644
--- a/Source/ActorImage.hpp
+++ b/Source/ActorImage.hpp
@@ -19,6 +19,7 @@
 
 	class ActorImage : public ActorNode
 	{
+		typedef ActorNode Base;
 		private:
 			int m_DrawOrder;
 			BlendModes m_BlendMode;
@@ -29,6 +30,7 @@
 			int m_TriangleCount;
 			float* m_AnimationDeformedVertices;
 			bool m_IsVertexDeformDirty;
+			float* m_BoneMatrices;
 
 			struct BoneConnection
 			{
@@ -36,14 +38,29 @@
 				ActorNode* node;
 				Mat2D bind;
 				Mat2D ibind;
+
+				BoneConnection();
 			};
 
+			int m_NumConnectedBones;
 			BoneConnection* m_BoneConnections;
 
 		public:
 			ActorImage();
+			~ActorImage();
 			ActorNode* makeInstance(Actor* resetActor);
 			void copy(ActorImage* node, Actor* resetActor);
+			void resolveNodeIndices(ActorNode** nodes);
+			bool doesAnimationVertexDeform();
+			void doesAnimationVertexDeform(bool doesIt);
+			float* animationDeformedVertices();
+			bool isVertexDeformDirty();
+			void isVertexDeformDirty(bool isIt);
+			int textureIndex();
+			void disposeGeometry();
+
+			int boneInfluenceMatricesLength();
+			float* boneInfluenceMatrices();
 
 			static ActorImage* read(Actor* actor, BlockReader* reader, ActorImage* node = NULL);
 	};
diff --git a/Source/BinaryReader.cpp b/Source/BinaryReader.cpp
index 071459a..82ba906 100644
--- a/Source/BinaryReader.cpp
+++ b/Source/BinaryReader.cpp
@@ -70,6 +70,30 @@
 	}
 }
 
+void BinaryReader::readUnsignedShortArray(unsigned short* numbers, unsigned int length)
+{
+	if(m_DataPosition+2*length > m_DataLength)
+	{
+		throw OverflowException("Attempt to read past end of data in BinaryReader::readUnsignedShortArray.");
+	}
+	for(int i = 0; i < length; i++)
+	{
+		unsigned char* bytes = &m_Data[m_DataPosition];
+		m_DataPosition += 2;
+
+		if(m_SwapEndianness)
+		{
+			unsigned char sbytes[2] = { bytes[1], bytes[0] };
+			*numbers = *reinterpret_cast<unsigned short*>(sbytes);
+		}
+		else
+		{
+			*numbers = *reinterpret_cast<unsigned short*>(bytes);
+		}
+		numbers++;
+	}
+}
+
 int BinaryReader::readInt()
 {
 	if(m_DataPosition+4 > m_DataLength)
diff --git a/Source/BinaryReader.hpp b/Source/BinaryReader.hpp
index ca3f1cb..13accd8 100644
--- a/Source/BinaryReader.hpp
+++ b/Source/BinaryReader.hpp
@@ -26,6 +26,7 @@
 			unsigned char readByte();
 			unsigned int read(unsigned char* bytes, unsigned int length);
 			void readFloatArray(float* numbers, unsigned int length);
+			void readUnsignedShortArray(unsigned short* numbers, unsigned int length);
 			int readInt();
 			unsigned int readUnsignedInt();
 			float readFloat();
diff --git a/Source/Solver.hpp b/Source/Solver.hpp
new file mode 100644
index 0000000..0f74ca2
--- /dev/null
+++ b/Source/Solver.hpp
@@ -0,0 +1,17 @@
+#ifndef _NIMA_SOLVER_HPP_
+#define _NIMA_SOLVER_HPP_
+
+namespace nima
+{
+	class Solver
+	{
+		public:
+			virtual int order() = 0;
+			virtual bool needsSolve() = 0;
+			virtual bool suppressMarkDirty() = 0;
+			virtual void suppressMarkDirty(bool suppressIt) = 0;
+			virtual void solveStart() = 0;
+			virtual void solve() = 0;
+	};
+}
+#endif
\ No newline at end of file